diff --git a/ChangeLog b/ChangeLog index 547f1cc..926bbfa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2005-01-15 Karl Runge + * rfb/rfb.h: add alphaSource and alphaPreMultiplied to rfbCursor. + * libvncserver/cursor.c: do cursor alpha blending in rfbDrawCursor() + for non-cursorshapeupdates clients. + * x11vnc: -alphablend, cursors fixes, -snapfb, more tweaks and bug + fixes. + 2004-12-27 Karl Runge * x11vnc: improve alpha channel handling for XFIXES cursors. * add more parameters to remote control. diff --git a/libvncserver/cursor.c b/libvncserver/cursor.c index 91dba3a..1600cb5 100644 --- a/libvncserver/cursor.c +++ b/libvncserver/cursor.c @@ -310,6 +310,8 @@ void rfbFreeCursor(rfbCursorPtr cursor) if(cursor) { if(cursor->cleanupRichSource && cursor->richSource) free(cursor->richSource); + if(cursor->cleanupRichSource && cursor->alphaSource) + free(cursor->alphaSource); if(cursor->cleanupSource && cursor->source) free(cursor->source); if(cursor->cleanupMask && cursor->mask) @@ -320,6 +322,7 @@ void rfbFreeCursor(rfbCursorPtr cursor) cursor->cleanup=cursor->cleanupSource=cursor->cleanupMask =cursor->cleanupRichSource=FALSE; cursor->source=cursor->mask=cursor->richSource=0; + cursor->alphaSource=0; } } @@ -489,12 +492,84 @@ void rfbDrawCursor(rfbScreenInfoPtr s) if(!c->richSource) rfbMakeRichCursorFromXCursor(s,c); - /* now the cursor has to be drawn */ - for(j=0;jmask[(j+j1)*w+(i+i1)/8]<<((i+i1)&7))&0x80) - memcpy(s->frameBuffer+(j+y1)*rowstride+(i+x1)*bpp, - c->richSource+(j+j1)*c->width*bpp+(i+i1)*bpp,bpp); + if (c->alphaSource) { + int rmax, rshift; + int gmax, gshift; + int bmax, bshift; + int amax = 255; /* alphaSource is always 8bits of info per pixel */ + unsigned long rmask, gmask, bmask; + + rmax = s->serverFormat.redMax; + gmax = s->serverFormat.greenMax; + bmax = s->serverFormat.blueMax; + rshift = s->serverFormat.redShift; + gshift = s->serverFormat.greenShift; + bshift = s->serverFormat.blueShift; + + rmask = (rmax << rshift); + gmask = (gmax << gshift); + bmask = (bmax << bshift); + + for(j=0;jmask[], + * using the extracted alpha value instead. + */ + char *dest, *src, *aptr; + unsigned long val, *dv, *sv; + int rdst, gdst, bdst; /* fb RGB */ + int asrc, rsrc, gsrc, bsrc; /* rich source ARGB */ + + dest = s->frameBuffer + (j+y1)*rowstride + (i+x1)*bpp; + src = c->richSource + (j+j1)*c->width*bpp + (i+i1)*bpp; + aptr = c->alphaSource + (j+j1)*c->width + (i+i1); + + dv = (unsigned long *)dest; + sv = (unsigned long *)src; + + asrc = *((unsigned char *)aptr); + + if (!asrc) { + continue; + } + + /* extract dest and src RGB */ + rdst = (*dv & rmask) >> rshift; /* fb */ + gdst = (*dv & gmask) >> gshift; + bdst = (*dv & bmask) >> bshift; + + rsrc = (*sv & rmask) >> rshift; /* richcursor */ + gsrc = (*sv & gmask) >> gshift; + bsrc = (*sv & bmask) >> bshift; + + /* blend in fb data. */ + if (! c->alphaPreMultiplied) { + rsrc = (asrc * rsrc)/amax; + gsrc = (asrc * gsrc)/amax; + bsrc = (asrc * bsrc)/amax; + } + rdst = rsrc + ((amax - asrc) * rdst)/amax; + gdst = gsrc + ((amax - asrc) * gdst)/amax; + bdst = bsrc + ((amax - asrc) * bdst)/amax; + + val = 0; + val |= (rdst << rshift); + val |= (gdst << gshift); + val |= (bdst << bshift); + + /* insert the cooked pixel into the fb */ + memcpy(dest, &val, bpp); + } + } + } else { + /* now the cursor has to be drawn */ + for(j=0;jmask[(j+j1)*w+(i+i1)/8]<<((i+i1)&7))&0x80) + memcpy(s->frameBuffer+(j+y1)*rowstride+(i+x1)*bpp, + c->richSource+(j+j1)*c->width*bpp+(i+i1)*bpp,bpp); + } if(wasChanged) rfbMarkRectAsModified(s,x1,y1,x1+x2,y1+y2); diff --git a/rfb/rfb.h b/rfb/rfb.h index 9364e8a..b3775bf 100644 --- a/rfb/rfb.h +++ b/rfb/rfb.h @@ -664,6 +664,8 @@ typedef struct rfbCursor { unsigned short foreRed, foreGreen, foreBlue; /* device-independent colour */ unsigned short backRed, backGreen, backBlue; /* device-independent colour */ unsigned char *richSource; /* source bytes for a rich cursor */ + unsigned char *alphaSource; /* source for alpha blending info */ + rfbBool alphaPreMultiplied; /* if richSource already has alpha applied */ } rfbCursor, *rfbCursorPtr; extern unsigned char rfbReverseByte[0x100]; diff --git a/x11vnc/ChangeLog b/x11vnc/ChangeLog index 641ffa7..0c7b673 100644 --- a/x11vnc/ChangeLog +++ b/x11vnc/ChangeLog @@ -1,3 +1,12 @@ +2005-01-15 Karl Runge + * adjust alpha blending parameters, -alphablend, handle 24bpp. + * add -snapfb snapshot fb, not clear how useful it is.. + * more functions etc for -pointer_mode 4, still not finished. + * scan_for_updates() "count only" mode. + * increase max shm size on Linux. + * -oa -logappend, -pm, -speeds + * fix bugs in -allow, -R connect, screen == NULL + 2004-12-27 Karl Runge * allow -DLIBVNCSERVER_HAVE_FOO=0 override everything * get_xfixes_cursor() try to more carefully convert alpha channel diff --git a/x11vnc/README b/x11vnc/README index 41d4c29..711e12b 100644 --- a/x11vnc/README +++ b/x11vnc/README @@ -1,5 +1,5 @@ -x11vnc README file Date: Mon Dec 27 17:23:28 EST 2004 +x11vnc README file Date: Sat Jan 15 23:37:28 EST 2005 The following information is taken from these URLs: @@ -170,12 +170,19 @@ x11vnc: a VNC server for real X displays (to [1]FAQ) (to [2]downloads) encoding will be extremely slow over a networked link, so you need to force the issue with -encodings "copyrect tight ...". + Some VNC viewers will do the ssh tunnelling for you automatically, the + TightVNC vncviewer does this when the "-via far-away.east" option is + supplied to it (this requires x11vnc to be already running on + far-away.east or having it started by [16]inetd(1)). See the 3rd + script example [17]below for more info. + If the machine you SSH into is not the same machine with the X display you wish to view (e.g. your company provides incoming SSH access to a - gateway machine), then you need to change the above to, e.g.: -L - 5900:otherhost:5900. Once logged in, you'll need to do a second login + gateway machine), then you need to change the above to, e.g.: "-L + 5900:otherhost:5900". Once logged in, you'll need to do a second login (ssh, rsh, etc.) to the workstation machine 'otherhost' and then start up x11vnc on it. + _________________________________________________________________ Scripts to automate tunneling: As discussed below, there may be some problems with port 5900 being available. If that happens, the above @@ -183,9 +190,11 @@ x11vnc: a VNC server for real X displays (to [1]FAQ) (to [2]downloads) However, if you "know" port 5900 will be free on the local and remote machines, you can easily automate the above two steps by using the x11vnc option -bg (forks into background after connection to the - display is set up) or using the -f option of ssh. A simple example - script, assuming no problems with port 5900 being taken on the local - or remote sides, looks like: + display is set up) or using the -f option of ssh. + + + A simple example script, assuming no problems with port 5900 being + taken on the local or remote sides, looks like: #!/bin/sh # usage: x11vnc_ssh : # e.g.: x11vnc_ssh snoopy.peanuts.com:0 @@ -206,6 +215,7 @@ do done See also rx11vnc.pl below. + _________________________________________________________________ Another method is to start the VNC viewer in listen mode "vncviewer -listen" and have x11vnc initiate a reverse connection using the @@ -226,6 +236,7 @@ vncviewer -encodings "$enc" -listen & pid=$! ssh -R 5500:localhost:5500 $host "$cmd" kill $pid + _________________________________________________________________ A third way is specific to the TightVNC vncviewer special option -via for gateways. The only tricky part is we need to start up x11vnc and @@ -246,51 +257,52 @@ export VNC_VIA_CMD vncviewer -via $host localhost:0 # must be TightVNC vncviewer. Of course if you already have the x11vnc running waiting for - connections (or have it started out of inetd(1)), you can simply use - the TightVNC vncviewer -via gateway host:port in its default mode to - provide secure ssh tunnelling. + connections (or have it started out of [18]inetd(1)), you can simply + use the TightVNC "vncviewer -via gateway host:port" in its default + mode to provide secure ssh tunnelling. + VNC password file: Also note in the first example script that the option "-rfbauth .vnc/passwd" provides additional protection by requiring a VNC password for every VNC viewer that connects. The - vncpasswd or storepasswd programs, or the x11vnc [16]-storepasswd + vncpasswd or storepasswd programs, or the x11vnc [19]-storepasswd option can be used to create the password file. x11vnc also has the - slightly less secure [17]-passwdfile and "-passwd XXXXX" options. + slightly less secure [20]-passwdfile and "-passwd XXXXX" options. Important: It is up to you to tell x11vnc to use password protection, it will not do it for you automatically. The same goes for encrypting the channel between the viewer and x11vnc: it is up to you to use ssh, stunnel, VPN, etc. Also look into the -allow and -localhost - [18]options and building x11vnc with [19]tcp_wrappers support to limit + [21]options and building x11vnc with [22]tcp_wrappers support to limit host access. _________________________________________________________________ Downloading x11vnc: - x11vnc is a contributed program to the [20]libvncserver project at + x11vnc is a contributed program to the [23]LibVNCServer project at SourceForge.net. I use libvncserver for all of the VNC aspects; I couldn't have done without it. The full source code may be found and downloaded (either file-release tarball or CVS tree) from the above - link. As of Dec 2004, the [21]x11vnc-0.7.tar.gz source package is - released (recommended download) . The [22]x11vnc 0.7 release notes. + link. As of Dec 2004, the [24]x11vnc-0.7.tar.gz source package is + released (recommended download) . The [25]x11vnc 0.7 release notes. The x11vnc package is the subset of the libvncserver package needed to - build the x11vnc program. Please do not use the LibVNCServer-0.6 + build the x11vnc program. (Please do not use the LibVNCServer-0.6 tarball: it contains an older, more buggy version of x11vnc (Oct 2003) - that you likely want to avoid. Also, you can get a copy of my latest, - bleeding edge [23]x11vnc.c file to replace the one in the above + that you likely want to avoid). Also, you can get a copy of my latest, + bleeding edge [26]x11vnc.c file to replace the one in the above packages or the one in the CVS tree and then rebuild. You can also - update the tcl/tk gui with the [24]tkx11vnc.h file. If you have an + update the tcl/tk gui with the [27]tkx11vnc.h file. If you have an older libvncserver source tree, you may need to switch on the OLD_TREE - near the top of the x11vnc.c file. + variable near the top of the x11vnc.c file. - See the [25]FAQ below for information about where you might obtain a + See the [28]FAQ below for information about where you might obtain a precompiled x11vnc binary from 3rd parties. To obtain VNC viewers for the viewing side (Windows, Mac OS, or Unix) try here: - * [26]http://www.tightvnc.com/download.html - * [27]http://www.realvnc.com/download-free.html - * [28]http://sourceforge.net/projects/cotvnc/ + * [29]http://www.tightvnc.com/download.html + * [30]http://www.realvnc.com/download-free.html + * [31]http://sourceforge.net/projects/cotvnc/ More tools: Here is a rsh/ssh wrapper script rx11vnc that attempts to automatically do the above Steps 1-3 for you (provided you have @@ -300,8 +312,8 @@ vncviewer -via $host localhost:0 # must be TightVNC vncviewer. that attempts to tunnel the vnc traffic through an ssh port redirection (and does not assume port 5900 is free). Have a look at them to see what they do and customize as needed: - * [29]rx11vnc wrapper script - * [30]rx11vnc.pl wrapper script to tunnel traffic thru ssh + * [32]rx11vnc wrapper script + * [33]rx11vnc.pl wrapper script to tunnel traffic thru ssh _________________________________________________________________ Building x11vnc: @@ -338,14 +350,14 @@ vncviewer -via $host localhost:0 # must be TightVNC vncviewer. Note: If configure cannot find these two libraries then TightVNC and ZRLE encoding support will be disabled, and you don't want that! (the TightVNC encoding gives very good compression and performance, it even - makes a noticable difference over a fast LAN) + makes a noticeable difference over a fast LAN) libjpeg is included in Solaris 9 and later (/usr/sfw/include and /usr/sfw/lib), and zlib in Solaris 8 and later (/usr/include and /usr/lib). To get the source for these libraries: libjpeg is available - at [31]ftp://ftp.uu.net/graphics/jpeg/ and zlib at - [32]http://www.gzip.org/zlib/. See also - [33]http://www.sunfreeware.com/ for Solaris binary packages of these + at [34]ftp://ftp.uu.net/graphics/jpeg/ and zlib at + [35]http://www.gzip.org/zlib/. See also + [36]http://www.sunfreeware.com/ for Solaris binary packages of these libraries. Here is a build script that indicates one way to pass the library @@ -387,7 +399,7 @@ ls -l ./x11vnc/x11vnc Then do make install or copy the binary to your desired destination. Note that on Solaris make is /usr/ccs/bin/make, so that is why the - above puts /usr/ccs/bin in PATH. Other important build utililties are + above puts /usr/ccs/bin in PATH. Other important build utilities are there too: ld, ar, etc. Also, it is probably a bad idea to have /usr/ucb in your PATH while building. @@ -408,7 +420,7 @@ ls -l ./x11vnc/x11vnc x11vnc/x11vnc.c file. (This problem has been fixed as of x11vnc 0.6.2 (Aug/2004)) - If you need to build on Solaris 2.5.1 or earlier, see [34]this + If you need to build on Solaris 2.5.1 or earlier, see [37]this workaround FAQ. Building on HP-UX: For jpeg and zlib you will need to do the same @@ -422,7 +434,7 @@ ls -l ./x11vnc/x11vnc Finally, there seems to be a bug with gcc on HP-UX 11.xx: something fails (in the gcc private header files?) and it thinks it cannot find gettimeofday(). As a workaround add this to CPPFLAGS: - -DLIBVNCSERVER_HAVE_GETTIMEOFDAY. You may get some warnings but we + -DLIBVNCSERVER_HAVE_GETTIMEOFDAY=1. You may get some warnings but we have verified that this generates working x11vnc binaries on HP-UX hppa and ia64. _________________________________________________________________ @@ -439,7 +451,7 @@ ls -l ./x11vnc/x11vnc a solid background while using x11vnc. You can turn the pretty background image back on when you are using the display directly. - I also find the [35]tightvnc encoding gives the best response for my + I also find the [38]tightvnc encoding gives the best response for my usage (Unix <-> Unix over cable modem). One needs a tightvnc-aware vncviewer to take advantage of this encoding. @@ -455,10 +467,10 @@ ls -l ./x11vnc/x11vnc option where NNNN is the desired port number. Options: x11vnc has (far too) many features that may be activated - via its [36]command line options. Useful options are -nap to use fewer + via its [39]command line options. Useful options are -nap to use fewer resources (it sleeps more between polls when activity is low) and -rfbauth passwd-file to use VNC password protection (the vncpasswd or - storepasswd programs, or the x11vnc [37]-storepasswd option can be + storepasswd programs, or the x11vnc [40]-storepasswd option can be used to create the password file). Algorithm: How does x11vnc do it? Rather brute-forcedly: it @@ -482,14 +494,14 @@ ls -l ./x11vnc/x11vnc first testing out the programs. You get an interesting "feedback" effect where vncviewer images keep popping up each one contained in the previous one and slightly shifted a bit by the window manager - decorations. There will be an [38]even more interesting effect if + decorations. There will be an [41]even more interesting effect if -scale is used. Also, if the XKEYBOARD is supported and the XBell "beeps" once, you get an infinite loop of beeps going off. Although all of this is mildly exciting it is not much use: you will normally run and display the viewer on a different machine! SunRay notes: You can run x11vnc on your (connected or disconnected) - [39]SunRay session (Please remember to use -nap and maybe -wait 200 to + [42]SunRay session (Please remember to use -nap and maybe -wait 200 to avoid being a resource hog! It also helps a bit to have a solid background color). You have to know the name of the machine your SunRay session X server is running on. You also need to know the X11 @@ -525,11 +537,11 @@ ls -l ./x11vnc/x11vnc be a factor of 10-50, and it usually takes about 0.5-1 sec to read in the whole video hardware framebuffer (5MB for 1280x1024 at depth 24). So whenever activity changes most of the screen there - is a delay of this length while x11vnc reads the changed regions - in. To get a sense of the read and write speeds of your video - card, you can run the benchmarks like: x11perf -getimage500, - x11perf -putimage500, x11perf -shmput500 and for XFree86 displays - with direct graphics access the dga command (press "b" to run the + is a delay of 0.5-1 sec while x11vnc reads the changed regions in. + To get a sense of the read and write speeds of your video card, + you can run the benchmarks like: x11perf -getimage500, x11perf + -putimage500, x11perf -shmput500 and for XFree86 displays with + direct graphics access the dga command (press "b" to run the benchmark and then after a few seconds press "q" to quit). On XFree86 it is actually possible to increase the framebuffer read speed considerably (5-50 times) by using the Shadow @@ -540,10 +552,10 @@ ls -l ./x11vnc/x11vnc of the /etc/X11/XF86Config file. Note that this disables 2D acceleration at the physical display and so likely defeats the purpose. Nevertheless this could be handy in some circumstances, - e.g. if the slower speed at the physical display was acceptable - (this seems to be true for most video cards these days). - Unfortunately it does not seem shadowfb can be turned on and off - dynamically... + e.g. if the slower speed while sitting at the physical display was + acceptable (this seems to be true for most video cards these + days). Unfortunately it does not seem shadowfb can be turned on + and off dynamically... * Somewhat surprisingly, the X11 mouse (cursor) shape is write-only and cannot be queried from the X server. So in x11vnc the cursor shape stays fixed at an arrow. (see the "-cursor X" and "-cursor @@ -554,7 +566,8 @@ ls -l ./x11vnc/x11vnc supplied. As of Dec/2004 x11vnc supports the XFIXES extension (in Xorg and Solaris 10) to query the X server for the exact cursor shape, this works pretty well except that cursors with - transparency (alpha channel) need to approximated via dithering. + transparency (alpha channel) need to approximated to solid RGB + values. * Audio from applications is of course not redirected (separate redirectors do exist, e.g. esd). The XBell() "beeps" will work if the X server supports the XKEYBOARD extension. (Note that on @@ -564,209 +577,251 @@ ls -l ./x11vnc/x11vnc Evidently a timing related bug and difficult to reproduce... * Using -threads can expose some bugs in libvncserver. - Please feel free to [40]contact me if you have any questions, + Please feel free to [43]contact me if you have any questions, problems, or comments about x11vnc, etc. _________________________________________________________________ x11vnc FAQ: - [41]Q-1: I can't get x11vnc to start up. It says "XOpenDisplay failed - ((null))" or "Xlib: connection to ":0.0" refused by server". What do I - need to do? - [42]Q-2: I can't get x11vnc and/or libvncserver to compile. + [Building and Starting] - [43]Q-3: Help, I need to run x11vnc on Solaris 2.5.1 and it doesn't + [44]Q-1: I can't get x11vnc to start up. It says "XOpenDisplay failed + (null)" or "Xlib: connection to ":0.0" refused by server" and then + exits. What do I need to do? + + [45]Q-2: I can't get x11vnc and/or libvncserver to compile. + + [46]Q-3: Help, I need to run x11vnc on Solaris 2.5.1 and it doesn't compile! If I try to run a binary built on Solaris 2.6 I get: relocation error: file x11vnc: symbol XConvertCase: referenced symbol not found - [44]Q-4: Where can I get a precompiled x11vnc binary for my Operating + [47]Q-4: Where can I get a precompiled x11vnc binary for my Operating System? - [45]Q-5: Where can I get a VNC Viewer binary (or source code) for the + [48]Q-5: Where can I get a VNC Viewer binary (or source code) for the Operating System I will be viewing from? - [46]Q-6: How can I see all of x11vnc's command line options and + [49]Q-6: How can I see all of x11vnc's command line options and documentation on how to use them? - [47]Q-7: I don't like typing arcane command line options every time I + [50]Q-7: I don't like typing arcane command line options every time I start x11vnc. What can I do? Is there a config file? Or a GUI? - [48]Q-8: Why does x11vnc exit as soon as the VNC viewer disconnects? - And why doesn't it allow more than one VNC viewer to connect at the - same time? + [51]Q-8: Can I make x11vnc more quiet and also go into the background + after starting up? + + [52]Q-9: Sometimes when a VNC viewer dies abruptly, x11vnc also dies + with the error message like: "Broken pipe". I'm using the -forever + mode and I want x11vnc to keep running. - [49]Q-9: I have two separate machine displays in front of me, one + [Win2VNC Related] + + [53]Q-10: I have two separate machine displays in front of me, one Windows the other X11: can I use x11vnc in combination with Win2VNC in dual-screen mode to pass the keystrokes and mouse motions to the X11 display? - [50]Q-10: I am running Win2VNC on my windows machine and trying to + [54]Q-11: I am running Win2VNC on my windows machine and trying to create a dual-screen mode with my second display by running "x11vnc -nofb". Whenever I initiate the connection Win2VNC quickly disconnects and x11vnc says something like: rfbProcessClientNormalMessage: read: Connection reset by peer - [51]Q-11: The X display I run x11vnc on is only 8 bits per pixel (bpp) + [Color Issues] + + [55]Q-12: The X display I run x11vnc on is only 8 bits per pixel (bpp) PseudoColor (i.e. only 256 distinct colors). The x11vnc colors may start out OK, but after a while the colors are incorrect in certain windows. - [52]Q-12: Color problems: Why are the colors for some windows messed + [56]Q-13: Color problems: Why are the colors for some windows messed up in x11vnc? BTW, I have an X display that has nice overlay/multi-depth visuals of different color depths: e.g. there are both depth 8 and 24 visuals available at the same time. - [53]Q-13: How do I figure out the window id to supply to the -id + [57]Q-14: How do I figure out the window id to supply to the -id windowid option? - [54]Q-14: Why don't menus or other transient windows come up when I am + [58]Q-15: Why don't menus or other transient windows come up when I am using the -id windowid option to view a single application window? - [55]Q-15: Can I use x11vnc to view and interact with an Xterminal + [59]Q-16: My X display is depth 24 at 24bpp (instead of the normal + depth 24 at 32bpp). I'm having lots of color and visual problems with + x11vnc and vncviewer. + + [Xterminals] + + [60]Q-17: Can I use x11vnc to view and interact with an Xterminal (e.g. NCD) that is not running UNIX and so x11vnc cannot be run on it directly? - [56]Q-16: Can I make x11vnc more quiet and also go into the background - after starting up? + [61]Q-18: How do I get my X permissions (MIT-MAGIC-COOKIE) correct for + a Unix/Linux machine acting as an Xterminal? - [57]Q-17: How do I stop x11vnc once it is running in the background? + [Remote Control] - [58]Q-18: Can I change settings in x11vnc without having to restart + [62]Q-19: How do I stop x11vnc once it is running in the background? + + [63]Q-20: Can I change settings in x11vnc without having to restart it? Is there a way to remote control it? - [59]Q-19: Can I limit which machines incoming VNC clients can connect + [Security and Permissions] + + [64]Q-21: Why does x11vnc exit as soon as the VNC viewer disconnects? + And why doesn't it allow more than one VNC viewer to connect at the + same time? + + [65]Q-22: Can I limit which machines incoming VNC clients can connect from? - [60]Q-20: How do I build x11vnc/libvncserver with libwrap + [66]Q-23: How do I build x11vnc/libvncserver with libwrap (tcp_wrappers) support? - [61]Q-21: Can I prompt the user at the local X display whether the + [67]Q-24: Can I prompt the user at the local X display whether the incoming VNC client should be accepted or not? Can I decide to make some clients view-only? How about running an arbitrary program to make the decisions? - [62]Q-22: How do I create a VNC password for use with x11vnc? + [68]Q-25: How do I create a VNC password for use with x11vnc? - [63]Q-23: How can I tunnel my connection to x11vnc via an encrypted + [69]Q-26: How can I tunnel my connection to x11vnc via an encrypted SSH channel between two Unix machines? - [64]Q-24: How can I tunnel my connection to x11vnc via an encrypted + [70]Q-27: How can I tunnel my connection to x11vnc via an encrypted SSH channel from Windows using an SSH client like Putty? - [65]Q-25: Does x11vnc support Unix usernames and passwords? Can I + [71]Q-28: Does x11vnc support Unix usernames and passwords? Can I further limit the set of Unix usernames who can connect to the VNC desktop? - [66]Q-26: Can I have two passwords for VNC viewers, one for full + [72]Q-29: Can I have two passwords for VNC viewers, one for full access and the other for view-only access to the display? - [67]Q-27: I use a screen-lock when I leave my workstation (e.g. + [73]Q-30: I use a screen-lock when I leave my workstation (e.g. xscreensaver or xlock). When I remotely access my workstation desktop via x11vnc I can unlock the desktop fine, but I am worried people will see my activities on the physical monitor. What can I do to prevent this, or at least make it more difficult? - [68]Q-28: Can I have x11vnc automatically lock the screen when I + [74]Q-31: Can I have x11vnc automatically lock the screen when I disconnect the VNC viewer? - [69]Q-29: Are reverse connections (i.e. the VNC server connecting to - the VNC viewer) using "vncviewer -listen" and vncconnect(1) supported? - - [70]Q-30: Sometimes when a VNC viewer dies abruptly, x11vnc also dies - with the error message like: "Broken pipe". I'm using the -forever - mode and I want x11vnc to keep running. + [Display Managers and Services] + + [75]Q-32: How can I run x11vnc as a "service" that is always + available? - [71]Q-31: How can I use x11vnc to connect to an X login screen like + [76]Q-33: How can I use x11vnc to connect to an X login screen like xdm, GNOME gdm, KDE kdm, or CDE dtlogin? (i.e. nobody is logged into an X session yet). - [72]Q-32: Can I run x11vnc out of inetd(1)? + [77]Q-34: Can I run x11vnc out of inetd(1)? How about xinetd(1)? - [73]Q-33: How do I make x11vnc work with the Java VNC viewer applet in + [78]Q-35: How do I make x11vnc work with the Java VNC viewer applet in a web browser? - [74]Q-34: Why isn't the mouse cursor shape (the little icon shape + [79]Q-36: Are reverse connections (i.e. the VNC server connecting to + the VNC viewer) using "vncviewer -listen" and vncconnect(1) supported? + + [Resource Usage and Performance] + + [80]Q-37: I have lots of memory, but why does x11vnc fail with + shmget: No space left on device or Minor opcode of failed + request: 1 (X_ShmAttach)? + + [81]Q-38: How can I make x11vnc use less system resources? + + [82]Q-39: How can I make x11vnc use MORE system resources? + + [83]Q-40: I use x11vnc over a slow link with high latency (e.g. dialup + modem), is there anything I can do to speed things up? + + [84]Q-41: When I drag windows around with the mouse or scroll up and + down things really bog down (unless I do the drag in a single, quick + motion). Is there anything to do to improve things? + + [Mouse Cursor Shapes] + + [85]Q-42: Why isn't the mouse cursor shape (the little icon shape where the mouse pointer is) correct as I move from window to window? - [75]Q-35: Why does the mouse arrow just stay in one corner in my + [86]Q-43: When using XFIXES cursorshape mode, some of the cursors look + really bad with extra black borders around the cursor and other cruft. + How can I improve their appearance? + + [87]Q-44: In XFIXES mode, are there any hacks to handle cursor + transparency ("alpha channel") exactly? + + [Mouse Pointer] + + [88]Q-45: Why does the mouse arrow just stay in one corner in my vncviewer, whereas my cursor (that does move) is just a dot? - [76]Q-36: Can I take advantage of the TightVNC extension to the VNC + [89]Q-46: Can I take advantage of the TightVNC extension to the VNC protocol where Cursor Positions Updates are sent back to all connected clients (i.e. passive viewers can see the mouse cursor being moved around by another viewer)? - [77]Q-37: Is it possible to swap the mouse buttons (e.g. left-handed + [90]Q-47: Is it possible to swap the mouse buttons (e.g. left-handed operation), or arbitrarily remap them? How about mapping button clicks to keystrokes, e.g. to partially emulate Mouse wheel scrolling? - [78]Q-38: When I drag windows around with the mouse or scroll up and - down things really bog down (unless I do the drag in a single, quick - motion). Is there anything to do to improve things? - - [79]Q-39: I have lots of memory, but why does x11vnc fail with - shmget: No space left on device or Minor opcode of failed - request: 1 (X_ShmAttach)? - - [80]Q-40: How can I make x11vnc use less system resources? + [Keyboard Issues] - [81]Q-41: How can I make x11vnc use MORE system resources? - - [82]Q-42: I use x11vnc over a slow link with high latency (e.g. dialup - modem), is there anything I can do to speed things up? - - [83]Q-43: How can I get my AltGr and Shift modifiers to work between + [91]Q-48: How can I get my AltGr and Shift modifiers to work between keyboards for different languages? - [84]Q-44: When I try to type a "<" (i.e. less than) instead I get ">" + [92]Q-49: When I try to type a "<" (i.e. less than) instead I get ">" (i.e. greater than)! Strangely, typing ">" works OK!! - [85]Q-45: I'm using an "international" keyboard (e.g. German "de", or + [93]Q-50: I'm using an "international" keyboard (e.g. German "de", or Danish "dk") and the -modtweak mode works well if the VNC viewer is run on a Unix/Linux machine with a similar keyboard. But if I run the VNC viewer on Unix/Linux with a different keyboard (e.g. "us") or Windows with any keyboard, I can't type some keys like: "@", "$", "<", ">", etc. How can I fix this? - [86]Q-46: When typing I sometimes get double, triple, or more of my + [94]Q-51: When typing I sometimes get double, triple, or more of my keystrokes repeated. I'm sure I only typed them once, what can I do? - [87]Q-47: The machine where I run x11vnc has an AltGr key, but the + [95]Q-52: The machine where I run x11vnc has an AltGr key, but the local machine where I run the VNC viewer does not. Is there a way I can map a local unused key to send an AltGr? How about a Compose key as well? - [88]Q-48: I have a Sun machine I run x11vnc on. Its Sun keyboard has + [96]Q-53: I have a Sun machine I run x11vnc on. Its Sun keyboard has just one Alt key labelled "Alt" and two Meta keys labelled with little diamonds. The machine where I run the VNC viewer only has Alt keys. How can I send a Meta keypress? (e.g. emacs needs this) - [89]Q-49: Can I map a keystroke to a mouse button click on the remote + [97]Q-54: Can I map a keystroke to a mouse button click on the remote machine? - [90]Q-50: The remote display is larger (in number of pixels) than the + [Screen Related Issues and Features] + + [98]Q-55: The remote display is larger (in number of pixels) than the local display I am running the vncviewer on. I don't like the vncviewer scrollbars, what I can do? - [91]Q-51: Does x11vnc support server-side framebuffer scaling? (E.g. + [99]Q-56: Does x11vnc support server-side framebuffer scaling? (E.g. to make the desktop smaller). - [92]Q-52: Does x11vnc work with Xinerama? (i.e. multiple monitors + [100]Q-57: Does x11vnc work with Xinerama? (i.e. multiple monitors joined together to form one big, single screen). - [93]Q-53: Can I use x11vnc on a multi-headed display that is not + [101]Q-58: Can I use x11vnc on a multi-headed display that is not Xinerama (i.e. separate screens :0.0, :0.1, ... for each monitor)? - [94]Q-54: Does x11vnc support the XRANDR (X Resize, Rotate and + [102]Q-59: Does x11vnc support the XRANDR (X Resize, Rotate and Reflection) extension? Whenever I rotate or resize the screen x11vnc just seems to crash. - [95]Q-55: Why is the view in my VNC viewer completely black? Or why is - everything flashing around randomly? + [103]Q-60: Why is the view in my VNC viewer completely black? Or why + is everything flashing around randomly? - [96]Q-56: I use Linux Virtual Consoles (VC's) to implement 'Fast User + [104]Q-61: I use Linux Virtual Consoles (VC's) to implement 'Fast User Switching' between users' sessions (e.g. Betty is on Ctrl-Alt-F7, Bobby is on Ctrl-Alt-F8, and Sid is on Ctrl-Alt-F1: they use those keystrokes to switch between their sessions). How come the view in a @@ -774,22 +829,27 @@ ls -l ./x11vnc/x11vnc otherwise all messed up unless the X session x11vnc is attached to is in the active VC? - [97]Q-57: Does the Clipboard/Selection get transferred between the - vncviewer and the X display? - - [98]Q-58: Why don't I hear the "Beeps" in my X session (e.g. when - typing tput bel in an xterm)? - - [99]Q-59: I am using x11vnc where my local machine has "popup/hidden + [105]Q-62: I am using x11vnc where my local machine has "popup/hidden taskbars" (e.g. GNOME or MacOS X) and the remote display where x11vnc runs also has "popup/hidden taskbars" (e.g. GNOME). When I move the mouse to the edge of the screen where the popups happen, the taskbars interfere and fight with each other in strange ways. What can I do? + + [Misc: Clipboard, Beeps, etc.] + + [106]Q-63: Does the Clipboard/Selection get transferred between the + vncviewer and the X display? + + [107]Q-64: Why don't I hear the "Beeps" in my X session (e.g. when + typing tput bel in an xterm)? _________________________________________________________________ + + [Building and Starting] + Q-1: I can't get x11vnc to start up. It says "XOpenDisplay failed - ((null))" or "Xlib: connection to ":0.0" refused by server". What do I - need to do? + (null)" or "Xlib: connection to ":0.0" refused by server" and then + exits. What do I need to do? For the former error, you need to specify the X display to connect to (it also needs to be on the same machine x11vnc is to run on). Set @@ -799,40 +859,40 @@ ls -l ./x11vnc/x11vnc For the latter error, you need to set up the X11 permissions correctly. See the xauth(1), Xsecurity(7), and xhost(1) man pages for much info. For example, you may need to set your XAUTHORITY - environment variable (or use the -auth option) to point to the correct - cookie file (e.g. /home/joe/.Xauthority or - /var/lib/xdm/authdir/authfiles/A:0-nRySEi), or simply be sure you run - x11vnc as the correct user (i.e. the user who owns the X session you - wish to view). Less safe, but if the owner of the X session runs xhost - +localhost one should be able to attach x11vnc to the session (from - the same machine). - - We have been informed that some recent Linux distribution display - managers set XAUTHORITY to random local filenames, e.g.: - /tmp/.gdmHaVtYy. So logging in as the correct user may not be - enough... you need to dig out where they have hidden the - MIT-MAGIC-COOKIE. The -e option to ps(1) may help, e.g.: ps wwwweaux | - tr ' ' '\n' | grep XAUTHORITY | sort -u - - Note: use of Display Manager (gdm, kdm, ...) auth cookie files (i.e. - from /var/..., /tmp/..., or elsewhere) may require modification via - xauth(1) to correctly include the display x11vnc refers to (e.g. xauth - -f cookie.file add :0 . 45be51ae2ce9dfbacd882ab3ef8e96b1, where - 45be51... was found from an xauth -f /var/... list) or other reasons. - See xauth(1) manpage for full details on how to transfer an - MIT-MAGIC-COOKIE between machines and displays. - - To test out your X11 permissions, set DISPLAY (and possibly - XAUTHORITY) and type xclock in the same place you will be typing (or - otherwise running) x11vnc. If a little clock comes up on the display, - that means the X11 permissions are OK. To test your X11 permissions - when logged into the display machine remotely, use xdpyinfo (if you - see the informational output about the display you know it connected - to the X server successfully). - - Important: if you cannot get your X11 permissions so that the xclock - or xdpyinfo tests work, x11vnc also will not work (all of these X - clients must be able to connect to the X server to function). + environment variable or use the -auth option to point to the correct + cookie file (e.g. /home/joe/.Xauthority or /var/gdm/:0.Xauth), or + simply be sure you run x11vnc as the correct user (i.e. the user who + owns the X session you wish to view). Running x11vnc as root is not + enough: you need to know where the XAUTHORITY file for the desired X + display is. Example: + x11vnc -display :0 -auth /var/gdm/:0.Xauth + + Less safe, but to avoid figuring out where the XAUTHORITY file is, if + the person sitting at the X session types "xhost +localhost" then one + should be able to attach x11vnc to the session (from the same + machine). The person could then type "xhost -localhost" after x11vnc + has connected to go back to the default permissions. + + Some Linux distributions or display managers may set XAUTHORITY to a + random local filename. You need to dig out where they have hidden the + MIT-MAGIC-COOKIE file (and set XAUTHORITY to it or use the -auth + option). This command is often useful to find non-standard settings + for XAUTHORITY: + ps wwwweaux | tr ' ' '\n' | grep XAUTHORITY | sort -u + + To test out your X11 permissions, set DISPLAY and possibly XAUTHORITY + (see your shell's man page, bash(1), tcsh(1), on how to set + environment variables) and type xdpyinfo in the same place you will be + typing (or otherwise running) x11vnc. If information is printed out + about the X display (screen sizes, supported extensions, color visuals + info) that means the X11 permissions are set up properly: xdpyinfo + successfully connected to DISPLAY. You could also type xclock and make + sure no errors are reported (a clock should appear on the X display, + type Ctrl-C to quit it) + + Important: if you cannot get your X11 permissions so that the xdpyinfo + or xclock tests work, x11vnc also will not work (all of these X + clients must be able to connect to the X server to function properly). Q-2: I can't get x11vnc and/or libvncserver to compile. @@ -881,7 +941,7 @@ ls -l ./x11vnc/x11vnc is a workaround for Solaris 2.5.1 (and perhaps earlier): First use the environment settings (CPPFLAGS, LDFLAGS, etc.) in the - above [100]Solaris build script to run the configure command. That + above [108]Solaris build script to run the configure command. That should succeed without failure. Then, you have to hand edit the autogenerated rfb/rfbconfig.h file in the source tree, and just before the last #endif at the bottom of that file insert these workaround @@ -918,20 +978,20 @@ typedef unsigned int in_addr_t; Q-4: Where can I get a precompiled x11vnc binary for my Operating System? - Hopefully the [101]build steps above and [102]FAQ provide enough info + Hopefully the [109]build steps above and [110]FAQ provide enough info for a painless compile for most environments. Please report problems with the x11vnc configure, make, etc. on your system (if your system is known to compile other GNU packages successfully). There are precompiled x11vnc binaries made by other groups available at the following locations: - Debian: (.deb) [103]http://packages.debian.org/x11vnc + Debian: (.deb) [111]http://packages.debian.org/x11vnc - Slackware: (.tgz) [104]http://www.linuxpackages.net/ Redhat/Fedora: - (.rpm) [105]http://dag.wieers.com/packages/x11vnc/ wwexptools: (.tgz) - [106]http://www.bell-labs.com/project/wwexptools/packages.html The + Slackware: (.tgz) [112]http://www.linuxpackages.net/ Redhat/Fedora: + (.rpm) [113]http://dag.wieers.com/packages/x11vnc/ wwexptools: (.tgz) + [114]http://www.bell-labs.com/project/wwexptools/packages.html The last one, wwexptools, provides a variety of Unix binaries (Linux, - Solaris, HP-UX, Irix, ...) with the intent of being compatible on a + Solaris, HP-UX, IRIX, ...) with the intent of being compatible on a wide range of OS releases. Find x11vnc near the bottom of that page and select 'download info'. @@ -941,12 +1001,15 @@ typedef unsigned int in_addr_t; this by looking at the x11vnc output and if it says the encoding for a client is "hextile" then likely the fast compression encodings are missing. If you want optimal performance on your OS, you should see - the [107]build notes above for where to download libz and libjpeg, and + the [115]build notes above for where to download libz and libjpeg, and then build everything with gcc. - If any of the above binaries don't work and building x11vnc on your OS - fails (and all else fails!) you can contact me as I often have a test - binary I could give you. + If the above binaries don't work and building x11vnc on your OS fails + (and all else fails!) you can try one of my motley collection of + [116]test binaries. Some may be old, some may have extra debugging + output, etc. One may work on your OS, but please understand they are + test/experimental binaries not intended for general usage like the + above precompiled ones from 3rd parties. As a general note, the x11vnc program is simple enough you don't really need to install a package: the binary will in most cases work @@ -965,14 +1028,14 @@ typedef unsigned int in_addr_t; To obtain VNC viewers for the viewing side (Windows, Mac OS, or Unix) try here: - * [108]http://www.tightvnc.com/download.html - * [109]http://www.realvnc.com/download-free.html - * [110]http://sourceforge.net/projects/cotvnc/ + * [117]http://www.tightvnc.com/download.html + * [118]http://www.realvnc.com/download-free.html + * [119]http://sourceforge.net/projects/cotvnc/ Q-6: How can I see all of x11vnc's command line options and documentation on how to use them? - Run: x11vnc -help The output is listed [111]here as well. + Run: x11vnc -help The output is listed [120]here as well. Q-7: I don't like typing arcane command line options every time I start x11vnc. What can I do? Is there a config file? Or a GUI? @@ -993,7 +1056,7 @@ x11vnc -nap -wait 50 -localhost -rfbauth $HOME/.vnc/passwd -display :0 $* taken as a command line option. E.g. the above would be: # this is a comment in my ~/.x11vncrc file nap -wait 50 # comment to the end of the line +wait 50 # this is a comment to the end of the line. -localhost # note: the leading "-" is optional. rfbauth /home/fred/.vnc/passwd display :0 @@ -1002,31 +1065,37 @@ display :0 As of Dec/2004 in the libvncserver CVS there is now a simple tcl/tk GUI based on the remote-control functionality that was added. It's not - particulary user-friendly, it just provides a point and click mode to + particularly user-friendly, it just provides a point and click mode to set all the many x11vnc parameters and obtain help on them. See the - -gui for more info. Examples: "x11vnc ... -gui" and "x11vnc ... -gui - other:0" in the latter case the gui is displayed on other:0 not the X - display x11vnc is polling. + -gui option for more info. Examples: "x11vnc ... -gui" and "x11vnc ... + -gui other:0" in the latter case the gui is displayed on other:0, not + the X display x11vnc is polling. - Q-8: Why does x11vnc exit as soon as the VNC viewer disconnects? And - why doesn't it allow more than one VNC viewer to connect at the same - time? + Q-8: Can I make x11vnc more quiet and also go into the background + after starting up? - These defaults are simple safety measures to avoid someone unknowingly - leaving his X11 desktop exposed (to the internet, say) for long - periods of time. Use the -forever option (aka -many) to have x11vnc - wait for more connections after the first client disconnects. Use the - -shared option to have x11vnc allow multiple clients to connect - simultaneously. + Use the -q and -bg options, respectively. (also: -quiet is an alias + for -q) - Recommended additional safety measures include using ssh ([112]see - above), stunnel, or a VPN to authenticate and encrypt the viewer - connections or to at least use the -rfbauth passwd-file [113]option to - use VNC password protection (or [114]-passwdfile) It is up to you to - apply these security measures, they will not be done for you - automatically. + Note that under -bg the stderr messages will be lost unless you use + the "-o logfile" option. + + Q-9: Sometimes when a VNC viewer dies abruptly, x11vnc also dies with + the error message like: "Broken pipe". I'm using the -forever mode and + I want x11vnc to keep running. + + As of Jan/2004 in the libvncserver CVS the SIGPIPE signal is ignored. + So if a viewer client terminates abruptly, libvncserver will notice on + the next I/O operation and will close the connection and continue on. + + As of Apr/2004 the above fix only works for BSD signal systems (Linux, + FreeBSD, ...) For SYSV systems there is a workaround in my + [121]x11vnc.c file. It also has an option -sigpipe exit to have x11vnc + clean up and exit upon receiving SIGPIPE. - Q-9: I have two separate machine displays in front of me, one Windows + [Win2VNC Related] + + Q-10: I have two separate machine displays in front of me, one Windows the other X11: can I use x11vnc in combination with Win2VNC in dual-screen mode to pass the keystrokes and mouse motions to the X11 display? @@ -1036,30 +1105,30 @@ display :0 secondary display (X11). Then start up Win2VNC on the primary display (Windows) referring it to the secondary display. - This will also work X11 to X11 using [115]x2vnc, however you would + This will also work X11 to X11 using [122]x2vnc, however you would probably just want to avoid VNC and use x2x for that. For reference, here are some links to Win2VNC-like programs for multiple monitor setups: - * [116]Original Win2VNC - * [117]Enhanced Win2VNC and [118]sourceforge link - * [119]x2vnc - * [120]x2x also [121]here - * [122]zvnc (MorphOS) + * [123]Original Win2VNC + * [124]Enhanced Win2VNC and [125]sourceforge link + * [126]x2vnc + * [127]x2x also [128]here + * [129]zvnc (MorphOS) All of them (except x2x) will work with x11vnc. - Q-10: I am running Win2VNC on my windows machine and trying to create + Q-11: I am running Win2VNC on my windows machine and trying to create a dual-screen mode with my second display by running "x11vnc -nofb". Whenever I initiate the connection Win2VNC quickly disconnects and x11vnc says something like: rfbProcessClientNormalMessage: read: Connection reset by peer Is the default visual of the X display you run x11vnc on low color - (e.g. 8 bit per pixel PseudoColor)? (you can run xdpyinfo to check). - There seems to be a bug in Win2VNC in that it cannot deal correctly - with colormaps (PseudoColor is the most common example of a visual - with a colormap). + (e.g. 8 bit per pixel PseudoColor)? (you can run xdpyinfo to check, + look in the "screen" section). There seems to be a bug in Win2VNC in + that it cannot deal correctly with colormaps (PseudoColor is the most + common example of a visual with a colormap). If so, there are a couple options. 1) Can you set the default visual on your display to be depth 24 TrueColor? Sun machines often have 8+24 @@ -1074,8 +1143,9 @@ display :0 So the visual will be set to 8bpp TrueColor and Win2VNC can handle this. Since Win2VNC does not use the framebuffer data there should be no problems in doing this. + [Color Issues] - Q-11: The X display I run x11vnc on is only 8 bits per pixel (bpp) + Q-12: The X display I run x11vnc on is only 8 bits per pixel (bpp) PseudoColor (i.e. only 256 distinct colors). The x11vnc colors may start out OK, but after a while the colors are incorrect in certain windows. @@ -1094,21 +1164,25 @@ display :0 non-zero in 8bpp PseudoColor on an obscure setup, and this option corrected the problems. - Q-12: Color problems: Why are the colors for some windows messed up in + Q-13: Color problems: Why are the colors for some windows messed up in x11vnc? BTW, I have an X display that has nice overlay/multi-depth visuals of different color depths: e.g. there are both depth 8 and 24 visuals available at the same time. - You may want to review the [123]previous question regarding 8 bpp + You may want to review the [130]previous question regarding 8 bpp PseudoColor. - If that isn't the problem, run xdpyinfo(1) to see what the default - visual is and what the depths of the other visuals are. Does the - default visual have a depth of 8? If it does, can you possibly - re-configure your X server to make the depth 24 visual the default? If - you can do it, this will save you a lot of grief WRT colors and x11vnc - (and for general usage too!). Here is how I do this on an old - Sparcstation 20 running Solaris 9 with SX graphics + On some hardware (Sun/SPARC, Sgi), the -overlay option discussed a + couple paragraphs down may solve this for you (you may want to skip to + it directly). + + Run xdpyinfo(1) to see what the default visual is and what the depths + of the other visuals are. Does the default visual have a depth of 8? + If it does, can you possibly re-configure your X server to make the + depth 24 visual the default? If you can do it, this will save you a + lot of grief WRT colors and x11vnc (and for general usage too!). Here + is how I do this on an old Sparcstation 20 running Solaris 9 with SX + graphics xinit -- -dev /dev/fb defclass TrueColor defdepth 24 and it works nicely (note: to log into console from the dtlogin @@ -1131,16 +1205,17 @@ TrueColor defdepth 24 "Overlay" "24,8" to support multi-depth overlays. For these, use the "-cc 4" X server command line option to get a depth 24 default visual. - Another option is if the system with overlay visuals is a Sun system - running Solaris you can use the -overlay x11vnc option (Aug/2004) to - have x11vnc use the Solaris XReadScreen(3X11) function to poll the - "true view" of the whole screen at depth 24 TrueColor.This is useful - for Legacy applications (older versions of Cadence CAD apps are - mentioned by x11vnc users) that require the default depth be 8bpp, or - will use a 8bpp visual even if depth 24 visuals are available, and so - the default depth workaround described in the previous paragraph is - not sufficient for these apps. The -overlay mode should also work on - IRIX machines. + The -overlay mode: Another option is if the system with overlay + visuals is a Sun system running Solaris you can use the -overlay + x11vnc option (Aug/2004) to have x11vnc use the Solaris + XReadScreen(3X11) function to poll the "true view" of the whole screen + at depth 24 TrueColor.This is useful for Legacy applications (older + versions of Cadence CAD apps are mentioned by x11vnc users) that + require the default depth be 8bpp, or will use a 8bpp visual even if + depth 24 visuals are available, and so the default depth workaround + described in the previous paragraph is not sufficient for these apps. + The -overlay mode should also work on IRIX machines using + XReadDisplay(3X11). Misc. notes on -overlay mode: An amusing by-product of -overlay mode is that mouse cursor shape is correct. The -overlay mode may be @@ -1164,14 +1239,14 @@ TrueColor defdepth 24 option works for Solaris machines with overlay visuals where most of this problem occurs. - Q-13: How do I figure out the window id to supply to the -id windowid + Q-14: How do I figure out the window id to supply to the -id windowid option? Run the xwininfo program in a terminal. It will ask you to click on the desired application window. After clicking, it will print out much information, including the window id. Also, the visual and depth of the window printed out is often useful in debugging x11vnc - [124]problems. + [131]problems. When using -id windowid, note that some VNC viewers will have problems rendering screens that have a width that is not a multiple of 4. Try @@ -1179,10 +1254,10 @@ TrueColor defdepth 24 Also, as of Dec/2004 libvncserver CVS you can use "-id pick" to have x11vnc run xwininfo(1) for you and after you click the window it - extracts the windowid. Besides "pick" there is also "root" to allow + extracts the windowid. Besides "pick" there is also "id:root" to allow you to go back to root window when doing remote-control. - Q-14: Why don't menus or other transient windows come up when I am + Q-15: Why don't menus or other transient windows come up when I am using the -id windowid option to view a single application window? This is related to the behavior of the XGetImage(3X11) and @@ -1199,7 +1274,46 @@ TrueColor defdepth 24 x11vnc is known to crash under both -id and -sid, so both modes are still experimental. Please report any reproducible bugs. - Q-15: Can I use x11vnc to view and interact with an Xterminal (e.g. + Q-16: My X display is depth 24 at 24bpp (instead of the normal depth + 24 at 32bpp). I'm having lots of color and visual problems with x11vnc + and vncviewer. + + First off, depth 24 at 24bpp (bpp=bits-per-pixel) is fairly uncommon + and can cause problems in general. It also can be slower than depth 24 + at 32bpp. You might want to switch to 32bpp (for XFree86 see the + "-fbbpp 32", DefaultFbBpp, FbBpp and related options). Perhaps you + have 24bpp because the video memory of the machine is low and the + screen wouldn't fit in video RAM at 32bpp. For this case depth 16 at + 16bpp might be an acceptable option. + + In any event x11vnc should handle depth 24 at 24bpp (although + performance may be slower). There are some caveats involving the + viewer however: + + The RealVNC Unix viewer cannot handle 24bpp from the server, it will + say: "main: setPF: not 8, 16 or 32 bpp?" and exit. I have not checked + the RealVNC Windows viewer. + + So you need to use the TightVNC Unix viewer. However there are some + problems with that too. It seems libvncserver does not do 24bpp + correctly with the Tight encoding. The colors and screen ultimately + get messed up. So you have to use a different encoding with the + TightVNC vncviewer, try "zlib", "hextile", or one of the other + encodings (e.g. vncviewer -encodings "zlib hextile" ...). I have not + checked the TightVNC or UltraVNC Windows viewers. + + It appears the older RealVNC Unix viewers (e.g. 3.3.3 and 3.3.7) can + handle 24bpp from the server, so you may want to use those. They + evidently request 32 bpp and libvncserver obliges. + + Now coming the opposite direction if you are running the vncviewer on + the 24bpp display, TightVNC will fail with "Can't cope with 24 + bits-per-pixel. Sorry." and RealVNC will fail with "main: Error: + couldn't find suitable pixmap format" so evidently you cannot use + 24bpp for the vncviewers to work on that X display. + [Xterminals] + + Q-17: Can I use x11vnc to view and interact with an Xterminal (e.g. NCD) that is not running UNIX and so x11vnc cannot be run on it directly? @@ -1217,16 +1331,50 @@ TrueColor defdepth 24 -flipbyteorder if the colors get messed up due to endian byte order differences. - Q-16: Can I make x11vnc more quiet and also go into the background - after starting up? + Q-18: How do I get my X permissions (MIT-MAGIC-COOKIE) correct for a + Unix/Linux machine acting as an Xterminal? - Use the -q and -bg options, respectively. (also: -quiet is an alias - for -q) + If the display machine is a traditional Xterminal (where the X server + runs on the Xterminal box, but all of the X client applications run on + a central server), the login display manager, and hence the + MIT-MAGIC-COOKIE auth files, are on the central server and not on the + Xterminal where the X server and x11vnc processes are running. Somehow + the MIT-MAGIC-COOKIE auth file data must be copied to the Xterminal. + If $HOME/.Xauthority is exported via NFS (this is insecure of course), + then x11vnc can simply pick it up via NFS (you may need to use the + -auth option to point to the correct file). Other options include + copying the auth file using scp, or something like: +central-server> xauth nextract - xterm123:0 | ssh xterm123 xauth nmerge - - Note that under -bg the stderr messages will be lost unless you use - the "-o logfile" option. + and then perhaps ssh from central-server to xterm123 to start x11vnc. + You can use "xauth -f /path/to/cookie.file list" to examine the + contents of the cookie in a file "/path/to/cookie.file". See the + xauth(1) manpage for more details. + + If the display name needs to be changed between the two hosts, see + [132]this note on the xauth add ... command. + + A less secure option is to run something like "xhost +127.0.0.1" to + allow cookie-free local access for x11vnc. + + If the Xterminal is really stripped down and doesn't have any user + accounts, NFS, etc. you'll need to contact your system administrator + to set something up. + + Not recommended, but as a last resort, you could have x11vnc [133]poll + the Xterminal over the network. + + Note: use of Display Manager (gdm, kdm, ...) auth cookie files (i.e. + from /var/..., /tmp/..., or elsewhere) may require modification via + xauth(1) to correctly include the display x11vnc refers to (e.g. + "xauth -f cookie.file add :0 . 45be51ae2ce9dfbacd882ab3ef8e96b1", + where 45be51... was found from an "xauth -f /var/... list") or other + reasons. See xauth(1) manpage for full details on how to transfer an + MIT-MAGIC-COOKIE between machines and displays. + + [Remote Control] - Q-17: How do I stop x11vnc once it is running in the background? + Q-19: How do I stop x11vnc once it is running in the background? As of Dec/2004 in the libvncserver CVS there is a remote control feature. It can change a huge amount of things on the fly: see the @@ -1236,23 +1384,23 @@ TrueColor defdepth 24 For older versions: If the -forever option has not been supplied, x11vnc will automatically exit after the first client disconnects. In - general you will have to kill the x11vnc process (however, see the - remote-control -R option below). This can be done via: "kill NNNNN" - (where NNNNN is the x11vnc process id number found from ps(1)), or - "pkill x11vnc", or "killall x11vnc" (Linux only). + general you will have to kill the x11vnc process This can be done via: + "kill NNNNN" (where NNNNN is the x11vnc process id number found from + ps(1)), or "pkill x11vnc", or "killall x11vnc" (Linux only). If you have not put x11vnc in the background via the -bg option or shell & operator, then simply press Ctrl-C in the shell where x11vnc - is running to stop it. If somehow your Keypress of Ctrl-C went through - x11vnc to the Xserver that then delivered it to x11vnc it is possible - one or both of the Ctrl or C keys will be left stuck in the pressed - down state in the Xserver. Tapping the stuck key (either via x11vnc or - at the physical console) will release it from the stuck state. If the - keyboard seems to be acting strangely it is often fixed by tapping - Ctrl, Shift, and Alt. Alternatively, the -clear_mods and -clear_keys - options can be used to release pressed keys at startup and exit. - - Q-18: Can I change settings in x11vnc without having to restart it? Is + is running to stop it. Potential Gotcha: If somehow your Keypress of + Ctrl-C went through x11vnc to the Xserver that then delivered it to + x11vnc it is possible one or both of the Ctrl or C keys will be left + stuck in the pressed down state in the Xserver. Tapping the stuck key + (either via x11vnc or at the physical console) will release it from + the stuck state. If the keyboard seems to be acting strangely it is + often fixed by tapping Ctrl, Shift, and Alt. Alternatively, the + -clear_mods and -clear_keys options can be used to release pressed + keys at startup and exit. + + Q-20: Can I change settings in x11vnc without having to restart it? Is there a way to remote control it? Look at the -remote (same as -R) and -query (same as -Q) options added @@ -1263,12 +1411,32 @@ TrueColor defdepth 24 commands do not start a x11vnc server, but rather communicate with one that is already running. The X display (VNC_CONNECT property) is used as the communication channel, so the X permissions and DISPLAY must be - set up correctly. + set up correctly for communication to be possible. There is also a simple tcl/tk gui based on this remote control mechanism. See the -gui option for more info. - Q-19: Can I limit which machines incoming VNC clients can connect + [Security and Permissions] + + Q-21: Why does x11vnc exit as soon as the VNC viewer disconnects? And + why doesn't it allow more than one VNC viewer to connect at the same + time? + + These defaults are simple safety measures to avoid someone unknowingly + leaving his X11 desktop exposed (to the internet, say) for long + periods of time. Use the -forever option (aka -many) to have x11vnc + wait for more connections after the first client disconnects. Use the + -shared option to have x11vnc allow multiple clients to connect + simultaneously. + + Recommended additional safety measures include using ssh ([134]see + above), stunnel, or a VPN to authenticate and encrypt the viewer + connections or to at least use the -rfbauth passwd-file [135]option to + use VNC password protection (or [136]-passwdfile) It is up to you to + apply these security measures, they will not be done for you + automatically. + + Q-22: Can I limit which machines incoming VNC clients can connect from? Yes, look at the -allow and -localhost options to limit connections by @@ -1279,12 +1447,13 @@ TrueColor defdepth 24 x11vnc -allow 192.168.0. for a subnet. For individual hosts you can use the hostname instead of - the IP number. Note that -localhost is the same as "-allow 127.0.0.1" + the IP number, e.g.: "-allow snoopy", and "-allow darkstar,wombat". + Note that -localhost is the same as "-allow 127.0.0.1" For more control, build libvncserver with libwrap support (tcp_wrappers) and then use /etc/hosts.allow. - Q-20: How do I build x11vnc/libvncserver with libwrap (tcp_wrappers) + Q-23: How do I build x11vnc/libvncserver with libwrap (tcp_wrappers) support? Here is one way to pass this information to the configure script: @@ -1299,11 +1468,11 @@ TrueColor defdepth 24 is "vnc", e.g.: vnc: 192.168.100.3 .example.com - Note that if you run x11vnc out of [125]inetd you do not need to build + Note that if you run x11vnc out of [137]inetd you do not need to build x11vnc with libwrap support because the /usr/sbin/tcpd reference in /etc/inetd.conf handles the tcp_wrappers stuff. - Q-21: Can I prompt the user at the local X display whether the + Q-24: Can I prompt the user at the local X display whether the incoming VNC client should be accepted or not? Can I decide to make some clients view-only? How about running an arbitrary program to make the decisions? @@ -1343,7 +1512,7 @@ TrueColor defdepth 24 program to prompt the user whether the client should be accepted or not. This requires that you have xmessage installed and available via PATH. In case it is not already on your system, the xmessage program - is available at [126]ftp://ftp.x.org/ + is available at [138]ftp://ftp.x.org/ To include view-only decisions for the external commands, prefix the command something like this: "yes:0,no:*,view:3 mycommand ..." This @@ -1382,7 +1551,7 @@ elif [ $rc = 4 ]; then fi exit 1 - Stefan Radman has written a nice dtksh script [127]dtVncPopup for use + Stefan Radman has written a nice dtksh script [139]dtVncPopup for use in CDE environments to do the same sort of thing. Information on how to use it is found at the top of the file. He encourages you to provide feedback to him to help improve the script. @@ -1398,7 +1567,7 @@ exit 1 variables are set as in "-accept command" (except that RFB_MODE will be "gone"). - Q-22: How do I create a VNC password for use with x11vnc? + Q-25: How do I create a VNC password for use with x11vnc? You may already have one in $HOME/.vnc/passwd if you have used, say, the vncserver program from the regular RealVNC or TightVNC packages @@ -1418,24 +1587,24 @@ exit 1 out for the command winding up in your shell's history file (history -c is often a way to clear it). - x11vnc also has the [128]-passwdfile and -passwd/-viewpasswd plain + x11vnc also has the [140]-passwdfile and -passwd/-viewpasswd plain text (i.e. not obscured like the -rfbauth VNC passwords) password options. - Q-23: How can I tunnel my connection to x11vnc via an encrypted SSH + Q-26: How can I tunnel my connection to x11vnc via an encrypted SSH channel between two Unix machines? - See the description earlier on this page on [129]how to tunnel VNC via + See the description earlier on this page on [141]how to tunnel VNC via SSH from Unix to Unix. A number of ways are described along with some issues you may encounter. Other secure encrypted methods exists, e.g. stunnel, IPSEC, various VPNs, etc. - Q-24: How can I tunnel my connection to x11vnc via an encrypted SSH + Q-27: How can I tunnel my connection to x11vnc via an encrypted SSH channel from Windows using an SSH client like Putty? - [130]Above we described how to tunnel VNC via SSH from Unix to Unix, + [142]Above we described how to tunnel VNC via SSH from Unix to Unix, you may want to review it. To do this from Windows using Putty it would go something like this: * In the Putty dialog window under 'Session' enter the hostname or @@ -1468,14 +1637,14 @@ exit 1 you'll need to do a second login (ssh or rsh) to the workstation machine 'otherhost' and then start up x11vnc on it. - As discussed [131]above another option is to first start the VNC + As discussed [143]above another option is to first start the VNC viewer in "listen" mode, and then launch x11vnc with the "-connection localhost" option to establish the reverse connection. In this case a Remote port redirection (not Local) is needed for port 5500 instead of 5900 (i.e. 'Source port: 5500' and 'Destination: localhost:5500' for a Remote connection). - Q-25: Does x11vnc support Unix usernames and passwords? Can I further + Q-28: Does x11vnc support Unix usernames and passwords? Can I further limit the set of Unix usernames who can connect to the VNC desktop? Until the VNC protocol and libvncserver support this things will be @@ -1489,7 +1658,7 @@ exit 1 connection to make it appear to emanate from the local machine. As discussed above, ssh is useful for this: ssh -l username -L 5900:localhost:5900 hostname ... See the ssh wrapper scripts mentioned - [132]elsewhere on this page. Of course a malicious user could allow + [144]elsewhere on this page. Of course a malicious user could allow other users to get in through his channel, but that is a problem with every method. Another thing to watch out for is a malicious user on the viewer side (where ssh is running) trying to sneak in through the @@ -1526,7 +1695,7 @@ exit 1 # reject it For this to work with ssh port redirection, the ssh option UsePrivilegeSeparation must be enabled. - Q-26: Can I have two passwords for VNC viewers, one for full access + Q-29: Can I have two passwords for VNC viewers, one for full access and the other for view-only access to the display? Yes, as of May/2004 in the libvncserver CVS there is the -viewpasswd @@ -1552,7 +1721,7 @@ exit 1 # reject it plain text passwords from $HOME/.vnc/passwd since it is very straight-forward to work out what to do from the VNC source code. - Q-27: I use a screen-lock when I leave my workstation (e.g. + Q-30: I use a screen-lock when I leave my workstation (e.g. xscreensaver or xlock). When I remotely access my workstation desktop via x11vnc I can unlock the desktop fine, but I am worried people will see my activities on the physical monitor. What can I do to prevent @@ -1565,7 +1734,7 @@ exit 1 # reject it In any event, as of Jun/2004 there is an experimental utility to make it more difficult for nosey people to see your x11vnc activities. The - source for it is [133]blockdpy.c The idea behind it is simple (but + source for it is [145]blockdpy.c The idea behind it is simple (but obviously not bulletproof): when a VNC client attaches to x11vnc put the display monitor in the DPMS "off" state, if the DPMS state ever changes immediately start up the screen-lock program. The x11vnc user @@ -1586,7 +1755,7 @@ exit 1 # reject it re-lock the screen before disconnecting!). Instructions can be found in the source code for the utility at the above link. - Q-28: Can I have x11vnc automatically lock the screen when I + Q-31: Can I have x11vnc automatically lock the screen when I disconnect the VNC viewer? Yes, a user mentions he uses the -gone option under CDE to run a @@ -1598,46 +1767,43 @@ exit 1 # reject it x11vnc -display :0.0 -forever -gone 'kdesktop_lock' x11vnc -display :0.0 -forever -gone 'xlock &' - Q-29: Are reverse connections (i.e. the VNC server connecting to the - VNC viewer) using "vncviewer -listen" and vncconnect(1) supported? - As of Mar/2004 in the libvncserver CVS x11vnc supports reverse - connections. On Unix one starts the VNC viewer in listen mode: - vncviewer -listen, and then startus up x11vnc with the -connect - option. To connect immediately at x11vnc startup time use the - "-connect host:port" option (use commas for a list of hosts to connect - to). The ":port" is optional (default is 5500). If a file is specified - instead: -connect /path/to/some/file then that file is checked - periodically (about once a second) for new hosts to connect to. + [Display Managers and Services] - To use the vncconnect(1) program (from the core VNC package at - www.realvnc.com) specify the -vncconnect option to x11vnc (Note: as of - Dec/2004 -vncconnect is now the default). vncconnect(1) must be - pointed to the same X11 DISPLAY as x11vnc (since it uses X properties - to communicate with x11vnc). If you do not have or do not want to get - the vncconnect(1) program, the following script (named "Vncconnect") - may work if your xprop(1) supports the -set option: -#!/bin/sh -# usage: Vncconnect -# Vncconnect -# note: not all xprop(1) support -set. -# -xprop -root -f VNC_CONNECT 8s -set VNC_CONNECT "$1" + Q-32: How can I run x11vnc as a "service" that is always available? - Q-30: Sometimes when a VNC viewer dies abruptly, x11vnc also dies with - the error message like: "Broken pipe". I'm using the -forever mode and - I want x11vnc to keep running. + There are a number of ways to do this. The primary thing you need to + decide is whether you want x11vnc to connect to the X session on the + machine 1) regardless of who (or if anyone) has the X session, or 2) + only if a certain user has the X session. Because X sessions are + protected by X permissions (XAUTHORITY and $HOME/.Xauthority) the + automatically started x11vnc will of course need to have sufficient + permissions. - As of Jan/2004 in the libvncserver CVS the SIGPIPE signal is ignored. - So if a viewer client terminates abruptly, libvncserver will notice on - the next I/O operation and will close the connection and continue on. + Here are some ideas: + * Use the description under "Continuously" in the [146]FAQ on x11vnc + and Display Managers + * Use the description in the [147]FAQ on x11vnc and inetd(1) + * Start x11vnc from $HOME/.xsession (or $HOME/.xinitrc) + * Although less reliable, see the [148]x11vnc_loop rc.local hack + below. - As of Apr/2004 the above fix only works for BSD signal systems (Linux, - FreeBSD, ...) For SYSV systems there is a workaround in my - [134]x11vnc.c file. It also has an option -sigpipe exit to have x11vnc - clean up and exit upon receiving SIGPIPE. + The display manager scheme will not be specific to which user has the + X session unless a test is specifically put into the display startup + script (often Xsetup). The inetd(1) scheme may or may not be specific + to which user has the X session (and it may not be able to do all + users via the XAUTHORITY permission issues). + + The $HOME/.xsession scheme is obviously is specific to a particular + user. If you do not know what a $HOME/.xsession script is or how to + use one, perhaps your desktop has a "session startup commands" + configuration option. The command to be run in the .xsession or + .xinitrc file may look like this: +x11vnc -logfile $HOME/.x11vnc.log -rfbauth $HOME/.vnc/passwd -forever -bg - Q-31: How can I use x11vnc to connect to an X login screen like xdm, + plus any other options you desire. + + Q-33: How can I use x11vnc to connect to an X login screen like xdm, GNOME gdm, KDE kdm, or CDE dtlogin? (i.e. nobody is logged into an X session yet). @@ -1655,14 +1821,18 @@ xprop -root -f VNC_CONNECT 8s -set VNC_CONNECT "$1" /var/lib/kdm/A:0-crWk72 for kdm, where the random characters in basename will vary a bit). - Another place to look for the auth file is via ps(1) output for the X - server process to find any -auth argument. + Tricks: another place to look for the auth file is via ps(1) output + for the X server process to find any -auth argument (e.g. ps wwwwaux | + grep auth). Also, sometimes this command is useful: ps wwwweaux | tr ' + ' '\n' | grep XAUTHORITY | sort -u gdm seems to have an annoying setting that causes x11vnc (and any other X clients) to be killed after the user logs in. Setting - KillInitClients=false in /etc/X11/gdm/gdm.conf may avoid this. + KillInitClients=false in the [daemon] section of /etc/X11/gdm/gdm.conf + avoids this. Otherwise, just restart x11vnc and then reconnect your + viewer. - For dtlogin in addition to the above sort of trick (the auth file + For dtlogin in addition to the above sort of trick (BTW, the auth file should be in /var/dt), you'll also need to add something like Dtlogin*grabServer:False to the Xconfig file (/etc/dt/config/Xconfig or /usr/dt/config/Xconfig on Solaris). Then restart dtlogin, e.g.: @@ -1673,11 +1843,11 @@ xprop -root -f VNC_CONNECT 8s -set VNC_CONNECT "$1" To make x11vnc always attached to the the X server (please consider the security implications of this!) including the login screen you - will need to add a command to the display manager startup script. The + will need to add a command to a display manager startup script. The name of the script file depends on desktop used and seem to be: - GNOME /etc/X11/gdm/PreSession/Default + GNOME /etc/X11/gdm/Init/Default (or Init/:0) KDE /etc/kde*/kdm/Xsetup - XDM /etc/X11/xdm/Xsetup + XDM /etc/X11/xdm/Xsetup (or xdm/Xsetup_0) CDE /etc/dt/config/Xsetup although the exact location can depend on operating system and @@ -1685,45 +1855,52 @@ xprop -root -f VNC_CONNECT 8s -set VNC_CONNECT "$1" kdm(1), xdm(1), dtlogin(1) for additional details. The above Dtlogin*grabServer:False step will be needed for dtlogin here as well. There may also be display number specific scripts: e.g. Xsetup_0 vs. - Xsetup. + Xsetup, you need to watch out for. + + In any event, the line you will add to the display manager script will + look something like: + /usr/local/bin/x11vnc -rfbauth /path/to/the/vnc/passwd -forever -bg + + where you should customize the exact command to your needs. Note that + we do not need to specify -display or -auth because happily they are + already set for us in the DISPLAY and XAUTHORITY environment + variables. - In any event, the line you will add to the script will look something - like: - /usr/local/bin/x11vnc -rfbauth /path/to/my/vnc/passwd -forever -bg + You may also want to force the VNC port with something like "-rfbport + 5900" - where you should customize the exact command to your needs. You may - want to redirect the x11vnc output to a separate log file for + You may want to redirect the x11vnc output to a separate log file for debugging. In that case replace the -bg above with something like: 1>> /var/tmp/x11vnc.log 2>&1 & (or use the "-o logfile" option). + Here is an example what we did on a vanilla install of Fedora-C3 + (seems to use gdm by default). Add a line like this to + /etc/X11/gdm/Init/:0 + /usr/local/bin/x11vnc -rfbauth /etc/x11vnc.passwd -forever -bg -o /var/tmp/x1 +1vnc.log + + And then add this line to /etc/X11/gdm/gdm.conf in the [daemon] + section: + KillInitClients=false + + Then restart: /usr/sbin/gdm-restart (or reboot). The + KillInitClients=false setting is important: without it x11vnc will be + killed immediately after the user logs in. Here are [149]full details + on how to configure gdm + If you do not want to deal with the display manager startup scripts, here is a kludgey script that can be run manually or out of a boot - file like rc.local. [135]x11vnc_loop It will need some local + file like rc.local. [150]x11vnc_loop It will need some local customization before running. Because the XAUTHORITY auth file must be guessed by this script, use of the display manager script above is preferred. - Xterminals: Note that if the display machine is a traditional - Xterminal (where the X server runs on the Xterminal box, but all of - the X client applications run on a central server), the login display - manager, and hence the auth files, are on the central server and not - on the Xterminal where the X server and x11vnc processes are running. - Somehow the MIT-COOKIE auth file data must be copied to the Xterminal - (e.g. via ssh, possibly using xauth nextract). You can use xauth -f - cookie.file list to test the contents of the cookie in a file - "cookie.file" - - Note: use of Display Manager (gdm, kdm, ...) auth cookie files (i.e. - from /var/..., /tmp/..., or elsewhere) may require modification via - xauth(1) to correctly include the display x11vnc refers to (e.g. xauth - -f cookie.file add :0 . 45be51ae2ce9dfbacd882ab3ef8e96b1, where - 45be51... was found from an xauth -f /var/... list) or other reasons. - See xauth(1) manpage for full details on how to transfer an - MIT-MAGIC-COOKIE between machines and displays. + If the machine is a traditional Xterminal you may want to read + [151]this FAQ. - Q-32: Can I run x11vnc out of inetd(1)? + Q-34: Can I run x11vnc out of inetd(1)? How about xinetd(1)? Yes, perhaps a line something like this in /etc/inetd.conf will do it for you: @@ -1733,9 +1910,8 @@ xprop -root -f VNC_CONNECT 8s -set VNC_CONNECT "$1" where the shell script /usr/local/bin/x11vnc_sh looks something like (you'll need to customize to your settings). #!/bin/sh -XAUTHORITY=/home/fred/.Xauthority; export XAUTHORITY -/usr/local/bin/x11vnc -inetd -display :0 -rfbauth /home/fred/.vnc/passwd 2>> /t -mp/x11vnc_sh.log +/usr/local/bin/x11vnc -inetd -display :0 -auth /home/fred/.Xauthority \ + -rfbauth /home/fred/.vnc/passwd 2>> /tmp/x11vnc_sh.log Note that you must redirect the standard error output to a log file or /dev/null for proper operation via inetd (otherwise the standard error @@ -1748,10 +1924,11 @@ mp/x11vnc_sh.log because the errors and warnings printed out are very useful in troubleshooting problems. - Note also the need to set XAUTHORITY to point to the MIT-COOKIE auth - file to get permission to connect to the X display (the x11vnc -auth - option could also have been used). See the x11vnc_loop file in the - previous question for more ideas on what that auth file may be, etc. + Note also the need to set XAUTHORITY via -auth to point to the + MIT-COOKIE auth file to get permission to connect to the X display + (setting and exporting the XAUTHORITY variable accomplishes the same + thing). See the x11vnc_loop file in the previous question for more + ideas on what that auth file may be, etc. On Solaris you cannot have the bare number 5900 in /etc/inetd.conf, you'll need to replace it with a word like x11vnc an then put @@ -1769,7 +1946,28 @@ mp/x11vnc_sh.log connecting to it. Always use a VNC password to further protect against unwanted access. - Q-33: How do I make x11vnc work with the Java VNC viewer applet in a + For xinetd(1), one user reports he created the file + /etc/xinetd.d/x11vncservice containing the following: +# default: off +# description: +service x11vncservice +{ + flags = REUSE NAMEINARGS + port = 5900 + type = UNLISTED + socket_type = stream + protocol = tcp + wait = no + user = root + server = /usr/sbin/tcpd + server_args = /usr/local/bin/x11vnc_sh + disable = no +} + + With the contents of /usr/local/bin/x11vnc_sh similar to the example + given above. + + Q-35: How do I make x11vnc work with the Java VNC viewer applet in a web browser? To have x11vnc serve up a Java VNC viewer applet to any web browsers @@ -1796,132 +1994,36 @@ mp/x11vnc_sh.log entirely from the viewer-side by having the jar file there and using either the java or appletviewer commands to run the program. - Q-34: Why isn't the mouse cursor shape (the little icon shape where - the mouse pointer is) correct as I move from window to window? - - On X servers supporting XFIXES or Overlay extensions this is possible. - See the paragraphs below. - - As mentioned above, the X11 mouse cursor shape (i.e. little picture: - an arrow, X, I-beam, resizer, etc) is one of the few write-only - objects in X11. That is, an application can tell the X server what the - cursor shape should be when the pointer is in a given window, but a - program (like x11vnc) unfortunately cannot read this information. I - believe this is because the cursor shape is often downloaded to the - graphics hardware (video card), but I could be mistaken. - - A simple kludge is provided by the "-cursor X" option that changes the - cursor when the mouse is on the root background (or any window has the - same cursor as the root background). Note that desktops like GNOME or - KDE often cover up the root background, so this won't work for those - cases. Also see the "-cursor some" option for additional kludges. - - Note that as of Aug/2004 in the libvncserver CVS, on Solaris using the - SUN_OVL overlay extension and IRIX, x11vnc can show the correct mouse - cursor when the -overlay is also supplied. (-overlay has some other - problems however, and can be slower). - - Also as of Dec/2004 in libvncserver CVS XFIXES X extension support has - been added to allow exact extraction of the mouse cursor shape. The - only issue is the handling of alpha channel transparency in cursors - (they must be approximated). XFIXES is available on recent Linux Xorg - based distros and Solaris 10 express (on Solaris you will need to add - "-L /usr/openwin/sfw/lib -R /usr/openwin/sfw/lib" to LDFLAGS for - configure to enable it). - - Q-35: Why does the mouse arrow just stay in one corner in my - vncviewer, whereas my cursor (that does move) is just a dot? - - This default takes advantage of a [136]tightvnc extension that allows - specifying a cursor image for the local VNC viewer. You may disable it - with the -nocursor option to x11vnc if your viewer does not have this - extension. - - Note: as of Aug/2004 in the libvncserver CVS this should be fixed: the - default for non-tightvnc viewers will be to draw the moving cursor - into the framebuffer. This can also be disabled via -nocursor. - - Q-36: Can I take advantage of the TightVNC extension to the VNC - protocol where Cursor Positions Updates are sent back to all connected - clients (i.e. passive viewers can see the mouse cursor being moved - around by another viewer)? - - Use the -cursorpos option when starting x11vnc. A VNC viewer must - support the Cursor Positions Updates for the user to see the mouse - motions (the TightVNC viewers support this). As of Aug/2004 in the - libvncserver CVS -cursorpos is the default. See -nocursorpos and - -nocursorshape. - - Q-37: Is it possible to swap the mouse buttons (e.g. left-handed - operation), or arbitrarily remap them? How about mapping button clicks - to keystrokes, e.g. to partially emulate Mouse wheel scrolling? - - You can remap the mouse buttons via something like: -buttonmap 13-31 - (or perhaps 12-21). Also, note that xmodmap(1) lets you directly - adjust the X server's button mappings, but in some circumstances it - might be more desirable to have x11vnc do it. - - One user had an X server with only one mouse button(!) and was able to - map all of the VNC client mouse buttons to it via: -buttonmap 123-111. - - Note that the -debug_pointer option prints out much info for every - mouse/pointer event. - - To map mouse button clicks to keystrokes you can use the alternate - format where the keystrokes are enclosed between colons like this - :: in place of the mouse button digit. For a sequence of - keysyms separate them with "+" signs. Button clicks can also be - included in the sequence via the fake keysyms Button1, etc. - - As an example, suppose the VNC viewer machine has a mouse wheel (these - generate button 4 and 5 events), but the machine that x11vnc is run on - only has the 3 regular buttons. In normal operation x11vnc will - discard the button 4 and 5 events. However, either of the following - button maps could possibly be of use emulating the mouse wheel events - in this case: - -buttonmap 12345-123:Prior::Next: - -buttonmap 12345-123:Up+Up+Up::Down+Down+Down: - - Exactly what keystroke "scrolling" events they should be bound to - depends on one's taste. If this method is too approximate, one could - consider not using -buttonmap but rather configuring the X server to - think it has a mouse with 5 buttons even though the physical mouse - does not. - - Note that when a keysym-mapped mouse button is clicked down this - immediately generates the key-press and key-release events (for each - keysym in turn if the mapping has a sequence of keysyms). When the - mouse button goes back up nothing is generated. - - If you include modifier keys like Shift_L instead of key-press - immediately followed by key-release the state of the modifier key is - toggled (however the initial state of the modifier key is ignored). So - to map the right button to type my name 'Karl Runge' I could use this: - -buttonmap 3-:Shift_L+k+Shift_L+a+r+l+space+Shift_L+r+Shift_L+u+n+g+e: - - (yes, this is getting a little silly). + Q-36: Are reverse connections (i.e. the VNC server connecting to the + VNC viewer) using "vncviewer -listen" and vncconnect(1) supported? - Q-38: When I drag windows around with the mouse or scroll up and down - things really bog down (unless I do the drag in a single, quick - motion). Is there anything to do to improve things? + As of Mar/2004 in the libvncserver CVS x11vnc supports reverse + connections. On Unix one starts the VNC viewer in listen mode: + vncviewer -listen, and then starts up x11vnc with the -connect option. + To connect immediately at x11vnc startup time use the "-connect + host:port" option (use commas for a list of hosts to connect to). The + ":port" is optional (default is 5500). If a file is specified instead: + -connect /path/to/some/file then that file is checked periodically + (about once a second) for new hosts to connect to. - As of Jan/2004 there are some improvements in the libvncserver CVS - tree. The default should now be much better than before and dragging - small windows around should no longer be a huge pain. If for some - reason these changes make matters worse, you can go back to the old - way via the -old_pointer option. + To use the vncconnect(1) program (from the core VNC package at + www.realvnc.com) specify the -vncconnect option to x11vnc (Note: as of + Dec/2004 -vncconnect is now the default). vncconnect(1) must be + pointed to the same X11 DISPLAY as x11vnc (since it uses X properties + to communicate with x11vnc). If you do not have or do not want to get + the vncconnect(1) program, the following script (named "Vncconnect") + may work if your xprop(1) supports the -set option: +#!/bin/sh +# usage: Vncconnect +# Vncconnect +# note: not all xprop(1) support -set. +# +xprop -root -f VNC_CONNECT 8s -set VNC_CONNECT "$1" - Also added was the -nodragging option that disables all screen updates - while dragging with the mouse (i.e. mouse motion with a button held - down). This gives the snappiest response, but might be undesired in - some circumstances when you want to see the visual feedback while - dragging (e.g. menu traversal or text selection). - As of Dec/2004 in the libvncserver CVS the -pointer_mode n option was - introduced. n=1 is the -old_pointer. See the -pointer_mode n help for - more info. + [Resource Usage and Performance] - Q-39: I have lots of memory, but why does x11vnc fail with shmget: + Q-37: I have lots of memory, but why does x11vnc fail with shmget: No space left on device or Minor opcode of failed request: 1 (X_ShmAttach)? @@ -1939,9 +2041,9 @@ mp/x11vnc_sh.log 19/03/2004 10:10:58 error creating tile-row shm for len=4 19/03/2004 10:10:58 reverting to single_copytile mode - Here is a shell script [137]shm_clear to list and prompt for removal + Here is a shell script [152]shm_clear to list and prompt for removal of your unattached shm segments (attached ones are skipped). I use it - while debugging x11vnc (I use shm_clear -y to assume "yes" for each + while debugging x11vnc (I use "shm_clear -y" to assume "yes" for each prompt). If x11vnc is regularly not cleaning up its shm segments, please contact me so we can work to improve the situation. @@ -1977,10 +2079,10 @@ ied) -fs 1.0 knocks it down to 2). If you are having much trouble with shm segments, consider disabling shm completely via the -noshm option. Performance will be somewhat degraded but when done over local machine - sockets it should be acceptable (see an [138]earlier question + sockets it should be acceptable (see an [153]earlier question discussing -noshm). - Q-40: How can I make x11vnc use less system resources? + Q-38: How can I make x11vnc use less system resources? The -nap and "-wait n" (where n is the sleep between polls in milliseconds, the default is 30 or so) option are good places to @@ -1989,7 +2091,7 @@ ied) -onetile option will use less memory and use fewer shared memory slots (add -fs 1.0 for one less slot). - Q-41: How can I make x11vnc use MORE system resources? + Q-39: How can I make x11vnc use MORE system resources? You can try -threads and dial down the wait time (e.g. -wait 1) and possibly dial down -defer as well. Note that if you try to increase @@ -2001,7 +2103,7 @@ ied) the x11vnc -id option) can be streamed over a LAN or wireless at a reasonable frame rate. - Q-42: I use x11vnc over a slow link with high latency (e.g. dialup + Q-40: I use x11vnc over a slow link with high latency (e.g. dialup modem), is there anything I can do to speed things up? Some things you might want to experiment with (most of which will help @@ -2025,7 +2127,7 @@ ied) worth it, but could be of use in some situations. VNC viewer parameters: - * Use a [139]TightVNC enabled viewer! + * Use a [154]TightVNC enabled viewer! * Make sure the tight encoding is being used (look at vncviewer and x11vnc outputs) * Request 8 bits per pixel using -bgr233 (up to 4X speedup over @@ -2054,10 +2156,224 @@ ied) * If you just want to watch one (simple) window use -id (cuts down extraneous polling and updates, but can be buggy or insufficient) * Set -nosel (disables all clipboard selection exchange) - * Use -nocursor (repainting the remote cursor position and shape - takes resources and round trips) + * Use -nocursor and -nocursorpos (repainting the remote cursor + position and shape takes resources and round trips) + + Q-41: When I drag windows around with the mouse or scroll up and down + things really bog down (unless I do the drag in a single, quick + motion). Is there anything to do to improve things? + + As of Jan/2004 there are some improvements in the libvncserver CVS + tree. The default should now be much better than before and dragging + small windows around should no longer be a huge pain. If for some + reason these changes make matters worse, you can go back to the old + way via the -pointer_mode 1 option. + + Also added was the -nodragging option that disables all screen updates + while dragging with the mouse (i.e. mouse motion with a button held + down). This gives the snappiest response, but might be undesired in + some circumstances when you want to see the visual feedback while + dragging (e.g. menu traversal or text selection). + + As of Dec/2004 in the libvncserver CVS the -pointer_mode n option was + introduced. n=1 is the original mose, n=2 and improvement, etc.. See + the -pointer_mode n help for more info. + + [Mouse Cursor Shapes] + + Q-42: Why isn't the mouse cursor shape (the little icon shape where + the mouse pointer is) correct as I move from window to window? + + On X servers supporting XFIXES or Overlay extensions this is possible. + See the paragraphs below. + + As mentioned above, the X11 mouse cursor shape (i.e. little picture: + an arrow, X, I-beam, resizer, etc) is one of the few write-only + objects in X11. That is, an application can tell the X server what the + cursor shape should be when the pointer is in a given window, but a + program (like x11vnc) unfortunately cannot read this information. I + believe this is because the cursor shape is often downloaded to the + graphics hardware (video card), but I could be mistaken. + + A simple kludge is provided by the "-cursor X" option that changes the + cursor when the mouse is on the root background (or any window has the + same cursor as the root background). Note that desktops like GNOME or + KDE often cover up the root background, so this won't work for those + cases. Also see the "-cursor some" option for additional kludges. + + Note that as of Aug/2004 in the libvncserver CVS, on Solaris using the + SUN_OVL overlay extension and IRIX, x11vnc can show the correct mouse + cursor when the -overlay is also supplied. (-overlay has some other + problems however, and can be slower). + + Also as of Dec/2004 in the libvncserver CVS XFIXES X extension support + has been added to allow exact extraction of the mouse cursor shape. + The only issue is the handling of alpha channel transparency in + cursors (they must be approximated). XFIXES is available on recent + Linux Xorg based distros and Solaris 10 express (on Solaris you will + need to add "-L /usr/openwin/sfw/lib -R /usr/openwin/sfw/lib" to + LDFLAGS for configure to enable it). + + Q-43: When using XFIXES cursorshape mode, some of the cursors look + really bad with extra black borders around the cursor and other cruft. + How can I improve their appearance? + + This happens for cursors with transparency ("alpha channel"); regular + X cursors (bitmaps) should be correct. Unfortunately x11vnc 0.7 was + released with a very poor algorithm for approximating the + transparency, which led to the ugly black borders. + + The problem is as follows: XFIXES allows x11vnc to retrieve the + current X server cursor shape, including the alpha channel for + transparency. For traditional bitmap cursors the alpha value will be 0 + for completely transparent pixels and 255 for completely opaque + pixels; whereas for modern, eye-candy cursors an alpha value between 0 + and 255 means to blend in the background colors to that degree with + the cursor colors. The pixel color blending formula is something like + this: Red = Red_cursor * a + Red_background * (1 - a), (where here 0 + =< a =< 1), with similar for Green and Blue. The VNC protocol does not + currently support an alpha channel in cursors: it only supports + regular X bitmap cursors and Rich Cursors that have RGB (Red, Green, + Blue) color data, but no "A" = alpha data. So x11vnc has to + approximate a cursor with transparency to create a Rich Cursor. This + is easier said than done: some cursor themes have cursors with + complicated drop shadows and other forms of translucency. + + Anyway, for the x11vnc 0.7.1 release the algorithm for approximating + transparency is much improved and hopefully gives decent cursor shapes + for most cursor themes. + + In case it still looks bad for your cursor theme, there are (of + course!) some tunable parameters. The "-alphacut n" option lets you + set the threshold "n" (between 0 and 255): cursor pixels with alpha + values below n will be considered completely transparent while values + equal to or above n will be completely opaque. The default is 240. The + "-alphafrac f" option tries to correct individual cursors that did not + fare well with the default -alphacut value: if a cursor has less than + fraction f (between 0.0 and 1.0) of its pixels selected by the default + -alphacut, the threshold is lowered until f of its pixels are + selected. The default fraction is 0.33. + + Finally, there is an option -alpharemove that is useful for themes + where many cursors are light colored (e.g. "whiteglass"). XFIXES + returns the cursor data with the RGB values pre-multiplied by the + alpha value. If the white cursors look too grey, specify -alpharemove + to brighten them by dividing out the alpha value. + + Q-44: In XFIXES mode, are there any hacks to handle cursor + transparency ("alpha channel") exactly? + + As of Jan/2005 in the libvncserver CVS, libvncserver has been modified + to allow an alpha channel (i.e. RGBA data) for Rich Cursors. This only + works if the screen pixel format has extra unused pixels where the + alpha data can be stored. This effectively limits things to depth 24 + at 32bpp (bpp = bits per pixel, depth = the number of bits used to + represent RGB color data and can be less than bpp); fortunately this + is a common screen setup. This hack won't work for 16bpp. (well, it + could work for depth 15 at 16bpp, but that only leaves one bit for the + alpha data, which is not worth it). + + The -alphablend option instructs x11vnc to use RGBA for Rich Cursors + (currently it is ignored except for depth 24 at 32bpp). So, in + -nocursorshape mode, or for VNC clients that do not support + CursorShapeUpdates (or have disabled them), x11vnc will draw the + blended cursor with transparency into the x11vnc framebuffer for these + clients, and the transparency should look correct for them. + + Now, if you want CursorShapeUpdates turned on for your viewer (e.g. + because you do not like the lag between your pointer and the drawn + cursor) it is possible to modify your VNC viewer to apply the alpha + channel blending locally. This hack is outside of the VNC protocol. + Not only does this require depth 24 at 32bpp (for the extra space to + hide the alpha data), but it also currently requires the client and + server to be of the same endianness (otherwise the hidden alpha data + gets reset to zero by the translation function). As an example, for + the TightVNC 1.3dev5 Unix vncviewer [155]this patch enables the + TightVNC viewer to do the blending locally. You have to set the + environment variable ALPHABLEND=1 before starting your modified + viewer. The patch code should give an example on how to change the + Windows TightVNC viewer to achieve the same thing (send me the patch + if you get that working). + + [Mouse Pointer] + + Q-45: Why does the mouse arrow just stay in one corner in my + vncviewer, whereas my cursor (that does move) is just a dot? + + This default takes advantage of a [156]tightvnc extension + (CursorShapeUpdates) that allows specifying a cursor image shape for + the local VNC viewer. You may disable it with the -nocursor option to + x11vnc if your viewer does not have this extension. + + Note: as of Aug/2004 in the libvncserver CVS this should be fixed: the + default for non-tightvnc viewers (or ones that do not support + CursorShapeUpdates) will be to draw the moving cursor into the x11vnc + framebuffer. This can also be disabled via -nocursor. + + Q-46: Can I take advantage of the TightVNC extension to the VNC + protocol where Cursor Positions Updates are sent back to all connected + clients (i.e. passive viewers can see the mouse cursor being moved + around by another viewer)? + + Use the -cursorpos option when starting x11vnc. A VNC viewer must + support the Cursor Positions Updates for the user to see the mouse + motions (the TightVNC viewers support this). As of Aug/2004 in the + libvncserver CVS -cursorpos is the default. See also -nocursorpos and + -nocursorshape. + + Q-47: Is it possible to swap the mouse buttons (e.g. left-handed + operation), or arbitrarily remap them? How about mapping button clicks + to keystrokes, e.g. to partially emulate Mouse wheel scrolling? + + You can remap the mouse buttons via something like: -buttonmap 13-31 + (or perhaps 12-21). Also, note that xmodmap(1) lets you directly + adjust the X server's button mappings, but in some circumstances it + might be more desirable to have x11vnc do it. + + One user had an X server with only one mouse button(!) and was able to + map all of the VNC client mouse buttons to it via: -buttonmap 123-111. + + Note that the -debug_pointer option prints out much info for every + mouse/pointer event. + + To map mouse button clicks to keystrokes you can use the alternate + format where the keystrokes are enclosed between colons like this + :: in place of the mouse button digit. For a sequence of + keysyms separate them with "+" signs. Look in the include file + , or use xev(1), or -debug_keyboard to fine the + keysym names. Button clicks can also be included in the sequence via + the fake keysyms Button1, etc. + + As an example, suppose the VNC viewer machine has a mouse wheel (these + generate button 4 and 5 events), but the machine that x11vnc is run on + only has the 3 regular buttons. In normal operation x11vnc will + discard the button 4 and 5 events. However, either of the following + button maps could possibly be of use emulating the mouse wheel events + in this case: + -buttonmap 12345-123:Prior::Next: + -buttonmap 12345-123:Up+Up+Up::Down+Down+Down: + + Exactly what keystroke "scrolling" events they should be bound to + depends on one's taste. If this method is too approximate, one could + consider not using -buttonmap but rather configuring the X server to + think it has a mouse with 5 buttons even though the physical mouse + does not. + + Note that when a keysym-mapped mouse button is clicked down this + immediately generates the key-press and key-release events (for each + keysym in turn if the mapping has a sequence of keysyms). When the + mouse button goes back up nothing is generated. - Q-43: How can I get my AltGr and Shift modifiers to work between + If you include modifier keys like Shift_L instead of key-press + immediately followed by key-release the state of the modifier key is + toggled (however the initial state of the modifier key is ignored). So + to map the right button to type my name 'Karl Runge' I could use this: + -buttonmap 3-:Shift_L+k+Shift_L+a+r+l+space+Shift_L+r+Shift_L+u+n+g+e: + + (yes, this is getting a little silly). + [Keyboard Issues] + + Q-48: How can I get my AltGr and Shift modifiers to work between keyboards for different languages? The option -modtweak should be of some use for this. It is a mode that @@ -2069,12 +2385,12 @@ ied) default (use -nomodtweak to get the old behavior). This was done because it was noticed on newer XFree86 setups even on bland "us" keyboards like "pc104 us" XFree86 included a "ghost" key with both "<" - and ">" it. This key does not exist on the keyboard (see [140]this FAQ + and ">" it. This key does not exist on the keyboard (see [157]this FAQ for more info). Without -modtweak there was then an ambiguity in the reverse map keysym => keycode, making it so the "<" symbol could not be typed. - Also see the [141]FAQ about the -xkb option for a more powerful method + Also see the [158]FAQ about the -xkb option for a more powerful method of modifier tweaking for use on X servers with the XKEYBOARD extension. @@ -2082,7 +2398,7 @@ ied) -debug_keyboard option prints out much info for every keystroke and so can be useful debugging things. - Q-44: When I try to type a "<" (i.e. less than) instead I get ">" + Q-49: When I try to type a "<" (i.e. less than) instead I get ">" (i.e. greater than)! Strangely, typing ">" works OK!! Does your keyboard have a single key with both "<" and ">" on it? Even @@ -2135,14 +2451,14 @@ ied) the keysym comma when it comes in from a client (so when Shift is down the comma press will yield "<"). - See also the [142]FAQ about the -xkb option as a possible workaround + See also the [159]FAQ about the -xkb option as a possible workaround using the XKEYBOARD extension. Note that of Jul/2004 in the libvncserver CVS the -modtweak option is now that default. Note that the -debug_keyboard option prints out much info for every keystroke to aid debugging keyboard problems. - Q-45: I'm using an "international" keyboard (e.g. German "de", or + Q-50: I'm using an "international" keyboard (e.g. German "de", or Danish "dk") and the -modtweak mode works well if the VNC viewer is run on a Unix/Linux machine with a similar keyboard. But if I run the VNC viewer on Unix/Linux with a different keyboard (e.g. "us") or @@ -2220,7 +2536,8 @@ ied) -remap asciitilde-dead_tilde,asciicircum-dead_circumflex etc. Use -remap filename if the list is long. Please send us your workarounds for this problem on your keyboard. Perhaps we can have - x11vnc adjust automatically at some point. + x11vnc adjust automatically at some point. See the -add_keysyms + option below. * To complement the above workaround using the -remap, an option -add_keysyms was added. This option instructs x11vnc to bind any unknown Keysyms coming in from VNC viewers to unused Keycodes in @@ -2230,7 +2547,7 @@ ied) is received from a VNC viewer, and only after that would -add_keysyms, or anything else, come into play. - Q-46: When typing I sometimes get double, triple, or more of my + Q-51: When typing I sometimes get double, triple, or more of my keystrokes repeated. I'm sure I only typed them once, what can I do? This may be due to an interplay between your X server's key autorepeat @@ -2270,7 +2587,7 @@ ied) someone is also working at the physical display and misses his autorepeating. - Q-47: The machine where I run x11vnc has an AltGr key, but the local + Q-52: The machine where I run x11vnc has an AltGr key, but the local machine where I run the VNC viewer does not. Is there a way I can map a local unused key to send an AltGr? How about a Compose key as well? @@ -2284,7 +2601,7 @@ ied) Super_R-Mode_switch,Menu-Multi_key" or use "-remap filename" to specify remappings from a file. - Q-48: I have a Sun machine I run x11vnc on. Its Sun keyboard has just + Q-53: I have a Sun machine I run x11vnc on. Its Sun keyboard has just one Alt key labelled "Alt" and two Meta keys labelled with little diamonds. The machine where I run the VNC viewer only has Alt keys. How can I send a Meta keypress? (e.g. emacs needs this) @@ -2301,7 +2618,7 @@ ied) send Alt_L in this case, maybe -remap Super_L-Meta_L would be a better choice. - Q-49: Can I map a keystroke to a mouse button click on the remote + Q-54: Can I map a keystroke to a mouse button click on the remote machine? This can be done directly in some X servers using AccessX and @@ -2317,13 +2634,15 @@ ied) -remap Super_R-Button2 maps the Super_R "flag" key press to the Button2 click, thereby making - pasting a bit easier. + X pasting a bit easier. Note that once the key goes down, the button down and button up events are generated immediately on the x11vnc side. When the key is released (i.e. goes up) no events are generated. - Q-50: The remote display is larger (in number of pixels) than the + [Screen Related Issues and Features] + + Q-55: The remote display is larger (in number of pixels) than the local display I am running the vncviewer on. I don't like the vncviewer scrollbars, what I can do? @@ -2341,17 +2660,19 @@ ied) There may also be scaling viewers out there (e.g. TightVNC on Windows) that automatically shrink or expand the remote framebuffer to fit the - local display. Especially for hand-held devices. See also [143]this - FAQ + local display. Especially for hand-held devices. See also [160]this + FAQ on x11vnc scaling. - Q-51: Does x11vnc support server-side framebuffer scaling? (E.g. to + Q-56: Does x11vnc support server-side framebuffer scaling? (E.g. to make the desktop smaller). As of Jun/2004 in the libvncserver CVS x11vnc provides basic server-side scaling. It is a global scaling of the desktop, not a per-client setting. To enable it use the "-scale fraction" option. "fraction" can either be a floating point number (e.g. -scale 0.5) or - the alternative m/n fraction notation (e.g. -scale 2/3). + the alternative m/n fraction notation (e.g. -scale 2/3). Note that if + fraction is greater than one the display is expanded (not clear how + useful this is). The current implementation is experimental in that it still needs to be optimized. Extra resources (CPU, memory I/O, and memory) are @@ -2374,10 +2695,11 @@ ied) that evidently causes the TightVNC to incorrectly detect the regions as image data and thereby introduce additional pixel artifacts due to the lossiness of the jpeg compression algorithm. Experiment to see if - -nojpeg improves the readability of text when using -scale to shrink - the display size. Also note that scaling may actually slow down the - transfer of text regions because after being scaled they do not - compress as well. + -nojpeg vncviewer option improves the readability of text when using + -scale to shrink the display size. Also note that scaling may actually + slow down the transfer of text regions because after being scaled they + do not compress as well. (this can often be a significant slowdown, + e.g. 10X). Another issue is that it appears VNC viewers require the screen width to be a multiple of 4. When scaling x11vnc will round the width to the @@ -2391,7 +2713,7 @@ ied) different scalings listening on separate ports (-rfbport option, etc.). - Q-52: Does x11vnc work with Xinerama? (i.e. multiple monitors joined + Q-57: Does x11vnc work with Xinerama? (i.e. multiple monitors joined together to form one big, single screen). Yes, it should generally work because it simply polls the big @@ -2418,7 +2740,7 @@ ied) function. (This may be due to a bug in the X server for XTEST when Xinerama is enabled). - Q-53: Can I use x11vnc on a multi-headed display that is not Xinerama + Q-58: Can I use x11vnc on a multi-headed display that is not Xinerama (i.e. separate screens :0.0, :0.1, ... for each monitor)? You can, but it is a little bit awkward: you must start separate @@ -2436,12 +2758,12 @@ ied) Note: if you are running on Solaris 8 or earlier you can easily hit up against the maximum of 6 shm segments per process (for Xsun in this case) from running multiple x11vnc processes. You should modify - /etc/system as mentioned in another [144]FAQ to increase the limit. It + /etc/system as mentioned in another [161]FAQ to increase the limit. It is probably also a good idea to run with the -onetile option in this case (to limit each x11vnc to 3 shm segments), or even -noshm to use no shm segments. - Q-54: Does x11vnc support the XRANDR (X Resize, Rotate and Reflection) + Q-59: Does x11vnc support the XRANDR (X Resize, Rotate and Reflection) extension? Whenever I rotate or resize the screen x11vnc just seems to crash. @@ -2461,12 +2783,12 @@ ied) specify "-xrandr exit" then all will be disconnected and x11vnc will terminate. - Q-55: Why is the view in my VNC viewer completely black? Or why is + Q-60: Why is the view in my VNC viewer completely black? Or why is everything flashing around randomly? See the next FAQ for a possible explanation. - Q-56: I use Linux Virtual Consoles (VC's) to implement 'Fast User + Q-61: I use Linux Virtual Consoles (VC's) to implement 'Fast User Switching' between users' sessions (e.g. Betty is on Ctrl-Alt-F7, Bobby is on Ctrl-Alt-F8, and Sid is on Ctrl-Alt-F1: they use those keystrokes to switch between their sessions). How come the view in a @@ -2493,7 +2815,21 @@ ied) x11vnc can poll it), one can use the switchto(1) command, e.g. "switchto 7" for VC #7. - Q-57: Does the Clipboard/Selection get transferred between the + Q-62: I am using x11vnc where my local machine has "popup/hidden + taskbars" (e.g. GNOME or MacOS X) and the remote display where x11vnc + runs also has "popup/hidden taskbars" (e.g. GNOME). When I move the + mouse to the edge of the screen where the popups happen, the taskbars + interfere and fight with each other in strange ways. What can I do? + + Is there a way to temporarily disable one or both of these magic + desktop taskbars? One x11vnc user suggests: it should be + straightforward to right mouse click on the task bar panel, and + uncheck "enable auto-hide" from the panel properties dialog box. This + will make the panel always visible. + + [Misc: Clipboard, Beeps, etc.] + + Q-63: Does the Clipboard/Selection get transferred between the vncviewer and the X display? As of Jan/2004 in the libvncserver CVS x11vnc supports the "CutText" @@ -2503,7 +2839,7 @@ ied) want the PRIMARY selection to be polled for changes use the -noprimary option. - Q-58: Why don't I hear the "Beeps" in my X session (e.g. when typing + Q-64: Why don't I hear the "Beeps" in my X session (e.g. when typing tput bel in an xterm)? As of Dec/2003 in the libvncserver CVS "Beep" XBell events are tracked @@ -2515,18 +2851,6 @@ ied) want to hear the audio from the remote applications, consider trying a redirector such as esd. - Q-59: I am using x11vnc where my local machine has "popup/hidden - taskbars" (e.g. GNOME or MacOS X) and the remote display where x11vnc - runs also has "popup/hidden taskbars" (e.g. GNOME). When I move the - mouse to the edge of the screen where the popups happen, the taskbars - interfere and fight with each other in strange ways. What can I do? - - Is there a way to temporarily disable one or both of these magic - desktop taskbars? One x11vnc user suggests: it should be - straightforward to right mouse click on the task bar panel, and - uncheck "enable auto-hide" from the panel properties dialog box. This - will make the panel always visible. - References 1. http://www.karlrunge.com/x11vnc/index.html#faq @@ -2544,135 +2868,152 @@ References 13. http://www.sun.com/software/solaris/freeware/ 14. http://www.karlrunge.com/x11vnc/x11vnc_opts.html 15. http://www.karlrunge.com/x11vnc/index.html#accept - 16. http://www.karlrunge.com/x11vnc/index.html#passwd - 17. http://www.karlrunge.com/x11vnc/index.html#passwdfile - 18. http://www.karlrunge.com/x11vnc/index.html#allow_opt - 19. http://www.karlrunge.com/x11vnc/index.html#tcp_wrappers - 20. http://sourceforge.net/projects/libvncserver/ - 21. http://sourceforge.net/project/showfiles.php?group_id=32584&package_id=119006&release_id=292078 - 22. http://sourceforge.net/project/shownotes.php?group_id=32584&release_id=292078 - 23. http://www.karlrunge.com/x11vnc/x11vnc.c - 24. http://www.karlrunge.com/x11vnc/tkx11vnc.h - 25. http://www.karlrunge.com/x11vnc/index.html#binaries - 26. http://www.tightvnc.com/download.html - 27. http://www.realvnc.com/download-free.html - 28. http://sourceforge.net/projects/cotvnc/ - 29. http://www.karlrunge.com/x11vnc/rx11vnc - 30. http://www.karlrunge.com/x11vnc/rx11vnc.pl - 31. ftp://ftp.uu.net/graphics/jpeg/ - 32. http://www.gzip.org/zlib/ - 33. http://www.sunfreeware.com/ - 34. http://www.karlrunge.com/x11vnc/index.html#solaris251build - 35. http://www.tightvnc.com/ - 36. http://www.karlrunge.com/x11vnc/x11vnc_opts.html - 37. http://www.karlrunge.com/x11vnc/index.html#passwd - 38. http://www.karlrunge.com/x11vnc/recurse_x11vnc.jpg - 39. http://wwws.sun.com/sunray/index.html - 40. mailto:xvml@karlrunge.com - 41. http://www.karlrunge.com/x11vnc/index.html#FAQ-1 - 42. http://www.karlrunge.com/x11vnc/index.html#FAQ-2 - 43. http://www.karlrunge.com/x11vnc/index.html#FAQ-3 - 44. http://www.karlrunge.com/x11vnc/index.html#FAQ-4 - 45. http://www.karlrunge.com/x11vnc/index.html#FAQ-5 - 46. http://www.karlrunge.com/x11vnc/index.html#FAQ-6 - 47. http://www.karlrunge.com/x11vnc/index.html#FAQ-7 - 48. http://www.karlrunge.com/x11vnc/index.html#FAQ-8 - 49. http://www.karlrunge.com/x11vnc/index.html#FAQ-9 - 50. http://www.karlrunge.com/x11vnc/index.html#FAQ-10 - 51. http://www.karlrunge.com/x11vnc/index.html#FAQ-11 - 52. http://www.karlrunge.com/x11vnc/index.html#FAQ-12 - 53. http://www.karlrunge.com/x11vnc/index.html#FAQ-13 - 54. http://www.karlrunge.com/x11vnc/index.html#FAQ-14 - 55. http://www.karlrunge.com/x11vnc/index.html#FAQ-15 - 56. http://www.karlrunge.com/x11vnc/index.html#FAQ-16 - 57. http://www.karlrunge.com/x11vnc/index.html#FAQ-17 - 58. http://www.karlrunge.com/x11vnc/index.html#FAQ-18 - 59. http://www.karlrunge.com/x11vnc/index.html#FAQ-19 - 60. http://www.karlrunge.com/x11vnc/index.html#FAQ-20 - 61. http://www.karlrunge.com/x11vnc/index.html#FAQ-21 - 62. http://www.karlrunge.com/x11vnc/index.html#FAQ-22 - 63. http://www.karlrunge.com/x11vnc/index.html#FAQ-23 - 64. http://www.karlrunge.com/x11vnc/index.html#FAQ-24 - 65. http://www.karlrunge.com/x11vnc/index.html#FAQ-25 - 66. http://www.karlrunge.com/x11vnc/index.html#FAQ-26 - 67. http://www.karlrunge.com/x11vnc/index.html#FAQ-27 - 68. http://www.karlrunge.com/x11vnc/index.html#FAQ-28 - 69. http://www.karlrunge.com/x11vnc/index.html#FAQ-29 - 70. http://www.karlrunge.com/x11vnc/index.html#FAQ-30 - 71. http://www.karlrunge.com/x11vnc/index.html#FAQ-31 - 72. http://www.karlrunge.com/x11vnc/index.html#FAQ-32 - 73. http://www.karlrunge.com/x11vnc/index.html#FAQ-33 - 74. http://www.karlrunge.com/x11vnc/index.html#FAQ-34 - 75. http://www.karlrunge.com/x11vnc/index.html#FAQ-35 - 76. http://www.karlrunge.com/x11vnc/index.html#FAQ-36 - 77. http://www.karlrunge.com/x11vnc/index.html#FAQ-37 - 78. http://www.karlrunge.com/x11vnc/index.html#FAQ-38 - 79. http://www.karlrunge.com/x11vnc/index.html#FAQ-39 - 80. http://www.karlrunge.com/x11vnc/index.html#FAQ-40 - 81. http://www.karlrunge.com/x11vnc/index.html#FAQ-41 - 82. http://www.karlrunge.com/x11vnc/index.html#FAQ-42 - 83. http://www.karlrunge.com/x11vnc/index.html#FAQ-43 - 84. http://www.karlrunge.com/x11vnc/index.html#FAQ-44 - 85. http://www.karlrunge.com/x11vnc/index.html#FAQ-45 - 86. http://www.karlrunge.com/x11vnc/index.html#FAQ-46 - 87. http://www.karlrunge.com/x11vnc/index.html#FAQ-47 - 88. http://www.karlrunge.com/x11vnc/index.html#FAQ-48 - 89. http://www.karlrunge.com/x11vnc/index.html#FAQ-49 - 90. http://www.karlrunge.com/x11vnc/index.html#FAQ-50 - 91. http://www.karlrunge.com/x11vnc/index.html#FAQ-51 - 92. http://www.karlrunge.com/x11vnc/index.html#FAQ-52 - 93. http://www.karlrunge.com/x11vnc/index.html#FAQ-53 - 94. http://www.karlrunge.com/x11vnc/index.html#FAQ-54 - 95. http://www.karlrunge.com/x11vnc/index.html#FAQ-55 - 96. http://www.karlrunge.com/x11vnc/index.html#FAQ-56 - 97. http://www.karlrunge.com/x11vnc/index.html#FAQ-57 - 98. http://www.karlrunge.com/x11vnc/index.html#FAQ-58 - 99. http://www.karlrunge.com/x11vnc/index.html#FAQ-59 - 100. http://www.karlrunge.com/x11vnc/index.html#solarisbuilding - 101. http://www.karlrunge.com/x11vnc/index.html#building - 102. http://www.karlrunge.com/x11vnc/index.html#buildfaq - 103. http://packages.debian.org/x11vnc - 104. http://www.linuxpackages.net/search_view.php?by=name&name=x11vnc - 105. http://dag.wieers.com/packages/x11vnc/ - 106. http://www.bell-labs.com/project/wwexptools/packages.html - 107. http://www.karlrunge.com/x11vnc/index.html#solarisbuilding - 108. http://www.tightvnc.com/download.html - 109. http://www.realvnc.com/download-free.html - 110. http://sourceforge.net/projects/cotvnc/ - 111. http://www.karlrunge.com/x11vnc/x11vnc_opts.html - 112. http://www.karlrunge.com/x11vnc/index.html#tunnelling - 113. http://www.karlrunge.com/x11vnc/index.html#passwd - 114. http://www.karlrunge.com/x11vnc/index.html#passwdfile - 115. http://fredrik.hubbe.net/x2vnc.html - 116. http://www.hubbe.net/~hubbe/win2vnc.html - 117. http://www.deboer.gmxhome.de/ - 118. http://sourceforge.net/projects/win2vnc/ - 119. http://fredrik.hubbe.net/x2vnc.html - 120. http://freshmeat.net/projects/x2x/ - 121. http://ftp.digital.com/pub/Digital/SRC/x2x/ - 122. http://zapek.com/software/zvnc/ - 123. http://www.karlrunge.com/x11vnc/index.html#8bpp - 124. http://www.karlrunge.com/x11vnc/index.html#overlays - 125. http://www.karlrunge.com/x11vnc/index.html#inetd - 126. ftp://ftp.x.org/ - 127. http://www.karlrunge.com/x11vnc/dtVncPopup - 128. http://www.karlrunge.com/x11vnc/index.html#passwdfile - 129. http://www.karlrunge.com/x11vnc/index.html#tunnelling - 130. http://www.karlrunge.com/x11vnc/index.html#tunnelling - 131. http://www.karlrunge.com/x11vnc/index.html#tunnelling - 132. http://www.karlrunge.com/x11vnc/index.html#tunnelling - 133. http://www.karlrunge.com/x11vnc/blockdpy.c - 134. http://www.karlrunge.com/x11vnc/x11vnc.c - 135. http://www.karlrunge.com/x11vnc/x11vnc_loop - 136. http://www.tightvnc.com/ - 137. http://www.karlrunge.com/x11vnc/shm_clear - 138. http://www.karlrunge.com/x11vnc/index.html#noshm - 139. http://www.tightvnc.com/ - 140. http://www.karlrunge.com/x11vnc/index.html#greaterless - 141. http://www.karlrunge.com/x11vnc/index.html#xkbmodtweak - 142. http://www.karlrunge.com/x11vnc/index.html#xkbmodtweak - 143. http://www.karlrunge.com/x11vnc/index.html#scaling - 144. http://www.karlrunge.com/x11vnc/index.html#solshm + 16. http://www.karlrunge.com/x11vnc/index.html#inetd + 17. http://www.karlrunge.com/x11vnc/index.html#tightvnc_via + 18. http://www.karlrunge.com/x11vnc/index.html#inetd + 19. http://www.karlrunge.com/x11vnc/index.html#passwd + 20. http://www.karlrunge.com/x11vnc/index.html#passwdfile + 21. http://www.karlrunge.com/x11vnc/index.html#allow_opt + 22. http://www.karlrunge.com/x11vnc/index.html#tcp_wrappers + 23. http://sourceforge.net/projects/libvncserver/ + 24. http://sourceforge.net/project/showfiles.php?group_id=32584&package_id=119006&release_id=292078 + 25. http://sourceforge.net/project/shownotes.php?group_id=32584&release_id=292078 + 26. http://www.karlrunge.com/x11vnc/x11vnc.c + 27. http://www.karlrunge.com/x11vnc/tkx11vnc.h + 28. http://www.karlrunge.com/x11vnc/index.html#binaries + 29. http://www.tightvnc.com/download.html + 30. http://www.realvnc.com/download-free.html + 31. http://sourceforge.net/projects/cotvnc/ + 32. http://www.karlrunge.com/x11vnc/rx11vnc + 33. http://www.karlrunge.com/x11vnc/rx11vnc.pl + 34. ftp://ftp.uu.net/graphics/jpeg/ + 35. http://www.gzip.org/zlib/ + 36. http://www.sunfreeware.com/ + 37. http://www.karlrunge.com/x11vnc/index.html#solaris251build + 38. http://www.tightvnc.com/ + 39. http://www.karlrunge.com/x11vnc/x11vnc_opts.html + 40. http://www.karlrunge.com/x11vnc/index.html#passwd + 41. http://www.karlrunge.com/x11vnc/recurse_x11vnc.jpg + 42. http://wwws.sun.com/sunray/index.html + 43. mailto:xvml@karlrunge.com + 44. http://www.karlrunge.com/x11vnc/index.html#FAQ-1 + 45. http://www.karlrunge.com/x11vnc/index.html#FAQ-2 + 46. http://www.karlrunge.com/x11vnc/index.html#FAQ-3 + 47. http://www.karlrunge.com/x11vnc/index.html#FAQ-4 + 48. http://www.karlrunge.com/x11vnc/index.html#FAQ-5 + 49. http://www.karlrunge.com/x11vnc/index.html#FAQ-6 + 50. http://www.karlrunge.com/x11vnc/index.html#FAQ-7 + 51. http://www.karlrunge.com/x11vnc/index.html#FAQ-8 + 52. http://www.karlrunge.com/x11vnc/index.html#FAQ-9 + 53. http://www.karlrunge.com/x11vnc/index.html#FAQ-10 + 54. http://www.karlrunge.com/x11vnc/index.html#FAQ-11 + 55. http://www.karlrunge.com/x11vnc/index.html#FAQ-12 + 56. http://www.karlrunge.com/x11vnc/index.html#FAQ-13 + 57. http://www.karlrunge.com/x11vnc/index.html#FAQ-14 + 58. http://www.karlrunge.com/x11vnc/index.html#FAQ-15 + 59. http://www.karlrunge.com/x11vnc/index.html#FAQ-16 + 60. http://www.karlrunge.com/x11vnc/index.html#FAQ-17 + 61. http://www.karlrunge.com/x11vnc/index.html#FAQ-18 + 62. http://www.karlrunge.com/x11vnc/index.html#FAQ-19 + 63. http://www.karlrunge.com/x11vnc/index.html#FAQ-20 + 64. http://www.karlrunge.com/x11vnc/index.html#FAQ-21 + 65. http://www.karlrunge.com/x11vnc/index.html#FAQ-22 + 66. http://www.karlrunge.com/x11vnc/index.html#FAQ-23 + 67. http://www.karlrunge.com/x11vnc/index.html#FAQ-24 + 68. http://www.karlrunge.com/x11vnc/index.html#FAQ-25 + 69. http://www.karlrunge.com/x11vnc/index.html#FAQ-26 + 70. http://www.karlrunge.com/x11vnc/index.html#FAQ-27 + 71. http://www.karlrunge.com/x11vnc/index.html#FAQ-28 + 72. http://www.karlrunge.com/x11vnc/index.html#FAQ-29 + 73. http://www.karlrunge.com/x11vnc/index.html#FAQ-30 + 74. http://www.karlrunge.com/x11vnc/index.html#FAQ-31 + 75. http://www.karlrunge.com/x11vnc/index.html#FAQ-32 + 76. http://www.karlrunge.com/x11vnc/index.html#FAQ-33 + 77. http://www.karlrunge.com/x11vnc/index.html#FAQ-34 + 78. http://www.karlrunge.com/x11vnc/index.html#FAQ-35 + 79. http://www.karlrunge.com/x11vnc/index.html#FAQ-36 + 80. http://www.karlrunge.com/x11vnc/index.html#FAQ-37 + 81. http://www.karlrunge.com/x11vnc/index.html#FAQ-38 + 82. http://www.karlrunge.com/x11vnc/index.html#FAQ-39 + 83. http://www.karlrunge.com/x11vnc/index.html#FAQ-40 + 84. http://www.karlrunge.com/x11vnc/index.html#FAQ-41 + 85. http://www.karlrunge.com/x11vnc/index.html#FAQ-42 + 86. http://www.karlrunge.com/x11vnc/index.html#FAQ-43 + 87. http://www.karlrunge.com/x11vnc/index.html#FAQ-44 + 88. http://www.karlrunge.com/x11vnc/index.html#FAQ-45 + 89. http://www.karlrunge.com/x11vnc/index.html#FAQ-46 + 90. http://www.karlrunge.com/x11vnc/index.html#FAQ-47 + 91. http://www.karlrunge.com/x11vnc/index.html#FAQ-48 + 92. http://www.karlrunge.com/x11vnc/index.html#FAQ-49 + 93. http://www.karlrunge.com/x11vnc/index.html#FAQ-50 + 94. http://www.karlrunge.com/x11vnc/index.html#FAQ-51 + 95. http://www.karlrunge.com/x11vnc/index.html#FAQ-52 + 96. http://www.karlrunge.com/x11vnc/index.html#FAQ-53 + 97. http://www.karlrunge.com/x11vnc/index.html#FAQ-54 + 98. http://www.karlrunge.com/x11vnc/index.html#FAQ-55 + 99. http://www.karlrunge.com/x11vnc/index.html#FAQ-56 + 100. http://www.karlrunge.com/x11vnc/index.html#FAQ-57 + 101. http://www.karlrunge.com/x11vnc/index.html#FAQ-58 + 102. http://www.karlrunge.com/x11vnc/index.html#FAQ-59 + 103. http://www.karlrunge.com/x11vnc/index.html#FAQ-60 + 104. http://www.karlrunge.com/x11vnc/index.html#FAQ-61 + 105. http://www.karlrunge.com/x11vnc/index.html#FAQ-62 + 106. http://www.karlrunge.com/x11vnc/index.html#FAQ-63 + 107. http://www.karlrunge.com/x11vnc/index.html#FAQ-64 + 108. http://www.karlrunge.com/x11vnc/index.html#solarisbuilding + 109. http://www.karlrunge.com/x11vnc/index.html#building + 110. http://www.karlrunge.com/x11vnc/index.html#buildfaq + 111. http://packages.debian.org/x11vnc + 112. http://www.linuxpackages.net/search_view.php?by=name&name=x11vnc + 113. http://dag.wieers.com/packages/x11vnc/ + 114. http://www.bell-labs.com/project/wwexptools/packages.html + 115. http://www.karlrunge.com/x11vnc/index.html#solarisbuilding + 116. http://www.karlrunge.com/x11vnc/bins + 117. http://www.tightvnc.com/download.html + 118. http://www.realvnc.com/download-free.html + 119. http://sourceforge.net/projects/cotvnc/ + 120. http://www.karlrunge.com/x11vnc/x11vnc_opts.html + 121. http://www.karlrunge.com/x11vnc/x11vnc.c + 122. http://fredrik.hubbe.net/x2vnc.html + 123. http://www.hubbe.net/~hubbe/win2vnc.html + 124. http://www.deboer.gmxhome.de/ + 125. http://sourceforge.net/projects/win2vnc/ + 126. http://fredrik.hubbe.net/x2vnc.html + 127. http://freshmeat.net/projects/x2x/ + 128. http://ftp.digital.com/pub/Digital/SRC/x2x/ + 129. http://zapek.com/software/zvnc/ + 130. http://www.karlrunge.com/x11vnc/index.html#8bpp + 131. http://www.karlrunge.com/x11vnc/index.html#overlays + 132. http://www.karlrunge.com/x11vnc/index.html#xauth_pain + 133. http://www.karlrunge.com/x11vnc/index.html#noshm + 134. http://www.karlrunge.com/x11vnc/index.html#tunnelling + 135. http://www.karlrunge.com/x11vnc/index.html#passwd + 136. http://www.karlrunge.com/x11vnc/index.html#passwdfile + 137. http://www.karlrunge.com/x11vnc/index.html#inetd + 138. ftp://ftp.x.org/ + 139. http://www.karlrunge.com/x11vnc/dtVncPopup + 140. http://www.karlrunge.com/x11vnc/index.html#passwdfile + 141. http://www.karlrunge.com/x11vnc/index.html#tunnelling + 142. http://www.karlrunge.com/x11vnc/index.html#tunnelling + 143. http://www.karlrunge.com/x11vnc/index.html#tunnelling + 144. http://www.karlrunge.com/x11vnc/index.html#tunnelling + 145. http://www.karlrunge.com/x11vnc/blockdpy.c + 146. http://www.karlrunge.com/x11vnc/index.html#display_manager + 147. http://www.karlrunge.com/x11vnc/index.html#inetd + 148. http://www.karlrunge.com/x11vnc/index.html#x11vnc_loop + 149. http://www.jirka.org/gdm-documentation/x241.html + 150. http://www.karlrunge.com/x11vnc/x11vnc_loop + 151. http://www.karlrunge.com/x11vnc/index.html#xterminal_xauth + 152. http://www.karlrunge.com/x11vnc/shm_clear + 153. http://www.karlrunge.com/x11vnc/index.html#noshm + 154. http://www.tightvnc.com/ + 155. http://www.karlrunge.com/x11vnc/tight-vncviewer-alphahack.patch + 156. http://www.tightvnc.com/ + 157. http://www.karlrunge.com/x11vnc/index.html#greaterless + 158. http://www.karlrunge.com/x11vnc/index.html#xkbmodtweak + 159. http://www.karlrunge.com/x11vnc/index.html#xkbmodtweak + 160. http://www.karlrunge.com/x11vnc/index.html#scaling + 161. http://www.karlrunge.com/x11vnc/index.html#solshm ======================================================================= @@ -2685,9 +3026,8 @@ x11vnc: a VNC server for real X displays Here are all of x11vnc command line options: % x11vnc -help - -x11vnc: allow VNC connections to real X11 displays. 0.7.1pre lastmod: 2004-12-2 -7 +x11vnc: allow VNC connections to real X11 displays. 0.7.1pre lastmod: 2005-01-1 +6 Typical usage is: @@ -2732,7 +3072,7 @@ Options: support MIT-SHM. Equivalent to setting the DISPLAY environment variable to "disp". -auth file Set the X authority file to be "file", equivalent to - setting the XAUTHORITY environment varirable to "file" + setting the XAUTHORITY environment variable to "file" before startup. See Xsecurity(7), xauth(1) man pages. -id windowid Show the window corresponding to "windowid" not @@ -2978,7 +3318,8 @@ Options: -remote id:windowid, rescaling, etc. -o logfile Write stderr messages to file "logfile" instead of - to the terminal. Same as "-logfile file". + to the terminal. Same as "-logfile file". To append + to the file use "-oa file" or "-logappend file". -rc filename Use "filename" instead of $HOME/.x11vncrc for rc file. -norc Do not process any .x11vncrc file for options. -h, -help Print this help text. @@ -3131,7 +3472,7 @@ Options: for cursors that have transparency ("alpha channel" with values ranging from 0 to 255) Any cursor pixel with alpha value less than n becomes completely transparent. - Otherwise the pixel is completely opaque. Default 255 + Otherwise the pixel is completely opaque. Default 240 Note: the options -alphacut, -alphafrac, and -alphafrac may be removed if a more accurate internal method for @@ -3147,6 +3488,14 @@ Options: black background). Specify this option to remove the alpha factor. (useful for light colored semi-transparent cursors). +-alphablend In XFIXES mode send cursor alpha channel data to + libvncserver. The blending effect will only be + visible in -nocursorshape mode or for clients with + cursorshapeupdates turned off. (However there is a + hack for 32bpp with depth 24, it uses the extra 8 bits + to store cursor transparency for use with a hacked + vncviewer that applies the transparency locally. + See the FAQ for more info). -nocursorshape Do not use the TightVNC CursorShapeUpdates extension even if clients support it. See -cursor above. @@ -3183,38 +3532,85 @@ Options: initial state of the modifier is ignored and not reset) To include button events use "Button1", ... etc. --nodragging Do not update the display during mouse dragging - events (mouse motion with a button held down). - Greatly improves response on slow setups, but you lose - all visual feedback for drags, text selection, and some - menu traversals. It overrides any -pointer_mode setting - (think of it as pointer_mode 0) --pointer_mode n Various pointer update schemes. The problem is pointer - motion can cause rapid changes on the screen, e.g. a - window drag. Neither x11vnc's screen polling nor the +-nodragging Do not update the display during mouse dragging events + (mouse button held down). Greatly improves response on + slow setups, but you lose all visual feedback for drags, + text selection, and some menu traversals. It overrides + any -pointer_mode setting +-pointer_mode n Various pointer motion update schemes. "-pm" is + an alias. The problem is pointer motion can cause + rapid changes on the screen: consider the rapid changes + when you drag a large window around. Neither x11vnc's + screen polling and vnc compression routines nor the bandwidth to the vncviewers can keep up these rapid - screen changes: everything bogs down when dragging - or scrolling. Note that most video h/w is optimized - for writing, not reading (a 50X rate difference is - possible) and x11vnc is reading all the time. So a - scheme has to be used to "eat" much of that pointer - input before re-polling the screen. n can be 1 to 4. - - n=1 was the original scheme used to about Jan 2004: it - basically just skips -input_skip pointer events before - repolling the screen. n=2 is an improved scheme: - by watching the current rate it tries to detect if - it should try to "eat" more pointer events. n=3 is - basically a dynamic -nodragging mode: it detects if the - mouse drag motion has paused and refreshes the display. - n=4 is TBD, it will try measure screen read and client - write rates and try to insert "frames" between the - on/off states of mode 3. The default n is 2. + screen changes: everything will bog down when dragging + or scrolling. So a scheme has to be used to "eat" + much of that pointer input before re-polling the screen + and sending out framebuffer updates. The mode number + "n" can be 0 to 4 and selects one of the schemes + desribed below. + + n=0: does the same as -nodragging. (all screen polling + is suspended if a mouse button is pressed.) + + n=1: was the original scheme used to about Jan 2004: + it basically just skips -input_skip keyboard or pointer + events before repolling the screen. + + n=2 is an improved scheme: by watching the current rate + of input events it tries to detect if it should try to + "eat" additional pointer events before continuing. + + n=3 is basically a dynamic -nodragging mode: it detects + when the mouse motion has paused and then refreshes + the display. + + n=4: attempts to measures network rates and latency, + the video card read rate, and how many tiles have been + changed on the screen. From this, it aggressively tries + to push screen "frames" when it decides it has enough + resources to do so. NOT FINISHED. + + The default n is 2. Note that modes 2, 3, 4 will skip + -input_skip keyboard events (but it will not count + pointer events). Also note that these modes are not + available in -threads mode which has its own pointer + event handling mechanism. + + To try out the different pointer modes to see + which one gives the best response for your usage, + it is convenient to use the remote control function, + e.g. "x11vnc -R pointer_mode:4" or the tcl/tk gui + (Tuning -> pointer_mode -> n). + -input_skip n For the pointer handling when non-threaded: try to read n user input events before scanning display. n < 0 means to act as though there is always user input. Default: 10 +-speeds rd,bw,lat x11vnc tries to estimate some speed parameters that + are used to optimize scheduling (e.g. -pointer_mode + 4) and other things. Use the -speeds option to set + these manually. The triple "rd,bw,lat" corresponds + to video h/w read rate in MB/sec, network bandwidth to + clients in KB/sec, and network latency to clients in + milliseconds, respectively. If a value is left blank, + e.g. "-speeds ,100,15", then the internal scheme is + used to estimate the empty value(s). + + Typical PC video cards have read rates of 5-10 MB/sec. + If the framebuffer is in main memory instead of video + h/w (e.g. SunRay, shadowfb, Xvfb), the read rate may + be much faster. "x11perf -getimage500" can be used + to get a lower bound (remember to factor in the bytes + per pixel). It is up to you to estimate the network + bandwith to clients. For the latency the ping(1) + command can be used. + + For convenience there are some aliases provided, + e.g. "-speeds modem". The aliases are: "modem" for + 6,4,200; "dsl" for 6,100,50; and "lan" for 6,5000,1 + -debug_pointer Print debugging output for every pointer event. -debug_keyboard Print debugging output for every keyboard event. Same as -dp and -dk, respectively. Use multiple @@ -3247,6 +3643,19 @@ Options: by checking the tile near the boundary. Default: 3 -fuzz n Tolerance in pixels to mark a tiles edges as changed. Default: 2 +-snapfb Instead of polling the X display framebuffer (fb) for + changes, periodically copy all of X display fb into main + memory and examine that copy for changes. Under some + circumstances this will improve interactive response, + or at least make things look smoother, but in others + (many) it will make the response worse. If the video + h/w fb is such that reading small tiles is very slow + this mode could help. To keep the "framerate" up + the screen size x bpp cannot be too large. Note that + this mode is very wasteful of memory I/O resources + (it makes full screen copies even if nothing changes). + It may be of use in video capture-like applications, + or where window tearing is a problem. -gui [gui-opts] Start up a simple tcl/tk gui based on the the remote control options -remote/-query described below. @@ -3433,6 +3842,8 @@ Options: alphafrac:f set -alphafrac to f. alpharemove enable -alpharemove mode. noalpharemove disable -alpharemove mode. + alphablend enable -alphablend mode. + noalphablend disable -alphablend mode. cursorshape disable -nocursorshape mode. nocursorshape enable -nocursorshape mode. cursorpos disable -nocursorpos mode. @@ -3442,8 +3853,9 @@ Options: buttonmap:str set -buttonmap "str", empty to disable dragging disable -nodragging mode. nodragging enable -nodragging mode. - pointer_mode n set -pointer_mode to n. - input_skip n set -input_skip to n. + pointer_mode:n set -pointer_mode to n. same as "pm" + input_skip:n set -input_skip to n. + speeds:str set -speeds to str. debug_pointer enable -debug_pointer, same as "dp" nodebug_pointer disable -debug_pointer, same as "nodp" debug_keyboard enable -debug_keyboard, same as "dk" @@ -3458,6 +3870,8 @@ Options: gaps:n set -gaps to n. grow:n set -grow to n. fuzz:n set -fuzz to n. + snapfb enable -snapfb mode. + nosnapfb disable -snapfb mode. progressive:n set libvncserver -progressive slice height parameter to n. desktop:str set -desktop name to str for new clients @@ -3518,29 +3932,30 @@ Options: variables correspond to the presence of X extensions): ans= stop quit exit shutdown ping blacken zero - refresh reset close disconnect id sid flashcmap - noflashcmap truecolor notruecolor overlay nooverlay - overlay_cursor overlay_yescursor nooverlay_nocursor - nooverlay_cursor nooverlay_yescursor overlay_nocursor - visual scale viewonly noviewonly shared noshared - forever noforever once deny lock nodeny unlock - connect allowonce allow localhost nolocalhost accept - gone shm noshm flipbyteorder noflipbyteorder onetile - noonetile blackout xinerama noxinerama xrandr noxrandr - xrandr_mode padgeom quiet q noquiet modtweak nomodtweak - xkb noxkb skip_keycodes add_keysyms noadd_keysyms - clear_mods noclear_mods clear_keys noclear_keys - remap repeat norepeat fb nofb bell nobell sel - nosel primary noprimary cursorshape nocursorshape + refresh reset close disconnect id sid waitmapped + nowaitmapped flashcmap noflashcmap truecolor notruecolor + overlay nooverlay overlay_cursor overlay_yescursor + nooverlay_nocursor nooverlay_cursor nooverlay_yescursor + overlay_nocursor visual scale viewonly noviewonly + shared noshared forever noforever once deny lock nodeny + unlock connect allowonce allow localhost nolocalhost + accept gone shm noshm flipbyteorder noflipbyteorder + onetile noonetile blackout xinerama noxinerama xrandr + noxrandr xrandr_mode padgeom quiet q noquiet modtweak + nomodtweak xkb noxkb skip_keycodes add_keysyms + noadd_keysyms clear_mods noclear_mods clear_keys + noclear_keys remap repeat norepeat fb nofb bell nobell + sel nosel primary noprimary cursorshape nocursorshape cursorpos nocursorpos cursor show_cursor noshow_cursor - nocursor xfixes noxfixes alphacut alphafrac alpharemove - noalpharemove xwarp xwarppointer noxwarp noxwarppointer - buttonmap dragging nodragging pointer_mode input_skip - debug_pointer dp nodebug_pointer nodp debug_keyboard - dk nodebug_keyboard nodk deferupdate defer wait - rfbwait nap nonap sb screen_blank fs gaps grow fuzz - progressive rfbport http nohttp httpport httpdir - enablehttpproxy noenablehttpproxy alwaysshared + nocursor xfixes noxfixes alphacut alphafrac + alpharemove noalpharemove alphablend noalphablend + xwarp xwarppointer noxwarp noxwarppointer buttonmap + dragging nodragging pointer_mode pm input_skip speeds + debug_pointer dp nodebug_pointer nodp debug_keyboard dk + nodebug_keyboard nodk deferupdate defer wait rfbwait + nap nonap sb screen_blank fs gaps grow fuzz snapfb + nosnapfb progressive rfbport http nohttp httpport + httpdir enablehttpproxy noenablehttpproxy alwaysshared noalwaysshared nevershared noalwaysshared dontdisconnect nodontdisconnect desktop noremote diff --git a/x11vnc/tkx11vnc b/x11vnc/tkx11vnc index 09e9782..d04ee67 100755 --- a/x11vnc/tkx11vnc +++ b/x11vnc/tkx11vnc @@ -139,6 +139,7 @@ Keyboard Pointer =-C:none,arrow,X,some,most cursor: noxfixes + alphablend -- cursorpos nocursorshape @@ -160,6 +161,7 @@ Misc bg =-C:ignore,exit sigpipe: =0 inetd + rfbwait: -- =RA remote-cmd: =GA all-settings @@ -204,17 +206,19 @@ Permissions unsafe Tuning - =-C:1,2,3,4 pointer_mode: + =-C:0,1,2,3,4 pointer_mode: input_skip: nodragging - alphacut: - alphafrac: - alpharemove -- =D noshm flipbyteorder onetile -- + alphacut: + alphafrac: + alpharemove + -- + speeds: wait: defer: nap @@ -224,9 +228,9 @@ Tuning gaps: grow: fuzz: + snapfb -- threads - rfbwait: -- progressive: " @@ -329,8 +333,7 @@ provides an interface to each of the many x11vnc command line options and remote control commands. See \"Help -> all\" for much info about x11vnc. Most menu items have a (?) button one can click on to get more information -about the option or command. In most cases it will be text extracted -from that in \"Help -> all\". +about the option or command. There are two states tkx11vnc can be in: @@ -463,7 +466,7 @@ proc make_toplevel {w {title ""}} { proc textwin {name title text} { global max_text_height max_text_width - global bfont + global bfont ffont set width [textwidth $text] incr width @@ -481,9 +484,11 @@ proc textwin {name title text} { frame $w.f -bd 0; pack $w.f -fill both -expand 1 text $w.f.t -width $width -height $height -setgrid 1 -bd 2 \ - -yscrollcommand "$w.f.y set" -relief ridge -font fixed; + -yscrollcommand "$w.f.y set" -relief ridge \ + -font $ffont; scrollbar $w.f.y -orient v -relief sunken -command "$w.f.t yview"; - button $w.f.b -text "Dismiss" -command "destroy $w" -font $bfont + button $w.f.b -text "Dismiss" -command "destroy $w" -font $bfont \ + -pady 2 $w.f.t insert 1.0 $text; @@ -909,121 +914,6 @@ proc entry_delete {} { # Utilities for remote control and updating vars. -proc push_new_value0 {item name new {query 1}} { - # old way w/o -sync - global menu_var always_update remote_output query_output - global delay_sleep extra_sleep extra_sleep_split - - set debug [in_debug_mode] - set do_query_all 0 - set getout 0 - - if {$item == "remote-cmd"} { - # kludge for arbitrary remote command: - if {[regexp {^Q:} $new]} { - # extra kludge for Q:var to mean -Q var - regsub {^Q:} $new "" new - set qonly 1 - } else { - set qonly 0 - } - # need to extract item from new: - set qtmp $new - regsub {:.*$} $qtmp "" qtmp - if {! $qonly} { - set rargs [list "-R" "$new"] - set qargs [list "-Q" "$qtmp"] - set getout 1 - } else { - set rargs [list "-Q" "$qtmp"] - set qargs [list "-Q" "$qtmp"] - } - - } elseif {[value_is_string $item]} { - set rargs [list "-R" "$name:$new"] - set qargs [list "-Q" "$name"] - } else { - set rargs [list "-R" "$name"] - set qargs [list "-Q" "$name"] - } - - if {!$debug} { - append_text "x11vnc $rargs ..." - } - set remote_output [run_remote_cmd $rargs] - - if {[lindex $rargs 0] == "-Q"} { - append_text "\t$remote_output" - set getout 1 - } elseif {! $query && ! $always_update} { - set getout 1 - } elseif {$item == "noremote"} { - set getout 1 - } elseif {[is_action $item] && ![opt_match Q $item] && $rargs != ""} { - set getout 1 - } elseif {[regexp {^(sid|id)$} $item] && ![regexp {^0x} $new]} { - set getout 1 - } - - if {$getout} { - append_text "\n" - return - } - - stop_watch on - after $delay_sleep - if {[opt_match D $item]} { - set s [expr $extra_sleep/$extra_sleep_split] - append_text " " - for {set i 0} {$i<$extra_sleep_split} {incr i} { - after $s - append_text "." - update - } - } - stop_watch off - - if {!$debug} { - append_text ", -Q ..." - } - - if {$item == "disconnect"} { - set new "N/A" - set do_query_all 1 - } - - if {$always_update || $do_query_all} { - set query [query_all 1] - } else { - set query [run_remote_cmd $qargs] - } - set query_output $query - - if {![see_if_ok $query $item "$name:$new"]} { - # failed - if {[regexp {^a..=} $query]} { - # but some result came back - if {! $always_update} { - # synchronize everything - set query_output [query_all 1] - } - } else { - # server may be dead - if {$item != "ping" && $item != "attach"} { - try_connect - } - } - } else { - # succeeded - if {! $always_update} { - # synchronize this variable - update_menu_vars $query - } else { - # already done in query_all - } - } -} - proc push_new_value {item name new {query 1}} { global menu_var always_update remote_output query_output global delay_sleep extra_sleep extra_sleep_split @@ -1264,6 +1154,25 @@ proc see_if_ok {query item expected} { } else { set msg $found } + if {!$ok && $found != ""} { + # check for floating point match: + set v1 "" + set v2 "" + regexp {:([0-9.][0-9.]*)$} $found m0 v1 + regexp {:([0-9.][0-9.]*)$} $expected m0 v2 + if {$v1 != "" && $v2 != ""} { + set diff "" + catch {set diff [expr "$v1 - $v2"]} + if {$diff != ""} { + if {$diff < 0} { + set diff [expr "0.0 - $diff"] + } + if {$diff < 0.00001} { + set ok 1 + } + } + } + } if {$ok} { append_text "\tSet OK ($msg)\n" return 1 @@ -1272,6 +1181,12 @@ proc see_if_ok {query item expected} { # e.g. blackout:+30x30+20+20 append_text "\t($msg)\n" return 1 + } elseif {[regexp {:[0-9]\.[0-9]} $expected]} { + append_text "\t($msg)\n" + return 1 + } elseif {$item == "connect" || $item == "disconnect"} { + append_text "\t($msg)\n" + return 1 } else { append_text "\t*FAILED* $msg\n" return 0 @@ -1298,13 +1213,14 @@ proc update_menu_vars {{query ""}} { if {$val == "N/A"} { continue } - if {0 && $debug} { - puts "setting menuvar: $item: $old -> $val" - } set menu_var($item) $val } if {$item == "clients"} { update_clients_menu $val + } elseif {$item == "display"} { + set_x11_display $val + } elseif {$item == "vncdisplay"} { + set_vnc_display $val } } } @@ -1329,6 +1245,7 @@ proc clear_all {} { } } } + append_text "Cleared all settings.\n" } proc all_query_vars {} { @@ -1813,10 +1730,10 @@ proc update_clients_and_repost {} { } proc update_clients_menu {list} { - global item_cascade + global item_cascade ffont set subm $item_cascade(current); catch {destroy $subm} - menu $subm -tearoff 0 + menu $subm -tearoff 0 -font $ffont $subm add command $subm add command -label "refresh-list" -command "update_clients_and_repost" $subm add separator @@ -1866,14 +1783,14 @@ proc make_widgets {} { global text_area global entry_box entry_str entry_set entry_label entry_ok entry_browse global entry_help entry_skip - global bfont + global bfont ffont global helptext helpremote helplabel set label_width 80 set info_label .info label $info_label -textvariable info_str -bd 2 -relief groove \ - -anchor w -width $label_width + -anchor w -width $label_width -font $ffont pack $info_label -side top -fill x -expand 0 # Extract the Rows: @@ -1989,11 +1906,13 @@ proc make_widgets {} { } elseif {$item == "Quit"} { # Quit item must shut us down: $m add command -label "$item" -underline 0 \ + -font $ffont \ -command {destroy .; exit 0} } elseif {$case == "Help"} { # Help is simple help: $m add command -label "$item" \ + -font $ffont \ -command "menu_help $item" } elseif {$item == "current"} { @@ -2002,11 +1921,13 @@ proc make_widgets {} { set item_cascade($item) $subm update_clients_menu "" $m add cascade -label "$item" \ + -font $ffont \ -menu $subm } elseif {[is_action $item]} { # Action $m add command -label "$item" \ + -font $ffont \ -command "do_var $item" set menu_var($item) ""; # for convenience @@ -2015,19 +1936,22 @@ proc make_widgets {} { if {[regexp -- {-C:(.*)} $item_opts($item) m0 m1]} { # Radiobutton select set subm $m.cascade$menu_count($case) - menu $subm -tearoff 0 + menu $subm -tearoff 0 -font $ffont foreach val [split $m1 ","] { $subm add radiobutton -label "$val" \ -command "do_var $item" \ -value "$val" \ + -font $ffont \ -variable menu_var($item) } $m add cascade -label "$item" \ + -font $ffont \ -menu $subm set item_cascade($item) $subm } else { # Arbitrary_string $m add command -label "$item" \ + -font $ffont \ -command "do_var $item" } set mvar 1 @@ -2036,6 +1960,7 @@ proc make_widgets {} { # Boolean $m add checkbutton -label "$item" \ -command "do_var $item" \ + -font $ffont \ -variable menu_var($item) set menu_var($item) 0 } @@ -2069,6 +1994,7 @@ proc make_widgets {} { set str "(?)" } $m add command -label $str \ + -font $ffont \ -command "menu_help $label"; if {$str == ""} { @@ -2094,17 +2020,19 @@ proc make_widgets {} { no_x11_display set lw [expr {$label_width / 2}] - label $df_x11 -textvariable x11_display -width $lw -anchor w + label $df_x11 -textvariable x11_display -width $lw -anchor w \ + -font $ffont set df_vnc "$df.vdisplay" no_vnc_display - label $df_vnc -textvariable vnc_display -width $lw -anchor w + label $df_vnc -textvariable vnc_display -width $lw -anchor w \ + -font $ffont pack $df_x11 $df_vnc -side left pack $df -side top -fill x # text area - text .text -height 11 -relief ridge + text .text -height 11 -relief ridge -font $ffont set text_area .text pack .text -side top -fill both -expand 1 @@ -2122,28 +2050,35 @@ proc make_widgets {} { set entry_str "Set... : " set ef_entry "$ef.entry" - entry $ef_entry -relief sunken + entry $ef_entry -relief sunken -font $ffont bind $ef_entry {set entry_set 1} bind $ef_entry {set entry_set 0} # Entry OK button + set bpx "1m" + set bpy "1" + set hlt "0" set ef_ok "$ef.ok" - button $ef_ok -text OK -pady 1 -command {set entry_set 1} \ + button $ef_ok -text OK -pady $bpy -padx $bpx -command {set entry_set 1} \ + -highlightthickness $hlt \ -font $bfont # Entry Skip button set ef_skip "$ef.skip" - button $ef_skip -text Skip -pady 0 -command {set entry_set 0} \ + button $ef_skip -text Skip -pady $bpy -padx $bpx -command {set entry_set 0} \ + -highlightthickness $hlt \ -font $bfont # Entry Help button set ef_help "$ef.help" - button $ef_help -text Help -pady 0 -command \ - {menu_help $entry_dialog_item} -font $bfont + button $ef_help -text Help -pady $bpy -padx $bpx -command \ + {menu_help $entry_dialog_item} -font $bfont \ + -highlightthickness $hlt # Entry Browse button set ef_browse "$ef.browse" - button $ef_browse -text "Browse..." -pady 0 -font $bfont \ + button $ef_browse -text "Browse..." -pady $bpy -padx $bpx -font $bfont \ + -highlightthickness $hlt \ -command {entry_insert [tk_getOpenFile]} pack $ef_label -side left @@ -2316,6 +2251,9 @@ proc get_start_x11vnc_cmd {{show_rc 0}} { if {$item == "id"} { set saw_id 1 } + if {$item == "httpport" && $menu_var($item) == "0"} { + continue + } if {$item == "progressive" && $menu_var($item) == "0"} { continue } @@ -2519,7 +2457,7 @@ global helpall helptext helpremote helplabel hostname; global all_settings reply_xdisplay always_update global max_text_height max_text_width global menu_var unset_str menus_disabled -global bfont old_labels +global bfont ffont old_labels global connected_to_x11vnc global delay_sleep extra_sleep extra_sleep_split global cache_all_query_vars @@ -2529,7 +2467,8 @@ set connected_to_x11vnc 0 set menus_disabled 0 set max_text_height 40 set max_text_width 90 -set bfont -adobe-helvetica-bold-r-*-*-*-120-*-*-*-*-*-*; +set bfont "-adobe-helvetica-bold-r-*-*-*-120-*-*-*-*-*-*" +set ffont "fixed" set help_indent 24; set reply_xdisplay "" set all_settings "None so far." diff --git a/x11vnc/tkx11vnc.h b/x11vnc/tkx11vnc.h index cf4beb7..2870d2e 100644 --- a/x11vnc/tkx11vnc.h +++ b/x11vnc/tkx11vnc.h @@ -145,6 +145,7 @@ "Pointer\n" " =-C:none,arrow,X,some,most cursor:\n" " noxfixes\n" +" alphablend\n" " --\n" " cursorpos\n" " nocursorshape\n" @@ -166,6 +167,7 @@ " bg\n" " =-C:ignore,exit sigpipe:\n" " =0 inetd\n" +" rfbwait:\n" " --\n" " =RA remote-cmd:\n" " =GA all-settings\n" @@ -210,17 +212,19 @@ " unsafe\n" "\n" "Tuning\n" -" =-C:1,2,3,4 pointer_mode:\n" +" =-C:0,1,2,3,4 pointer_mode:\n" " input_skip:\n" " nodragging\n" -" alphacut:\n" -" alphafrac:\n" -" alpharemove\n" " --\n" " =D noshm\n" " flipbyteorder\n" " onetile\n" " --\n" +" alphacut:\n" +" alphafrac:\n" +" alpharemove\n" +" --\n" +" speeds:\n" " wait:\n" " defer:\n" " nap\n" @@ -230,9 +234,9 @@ " gaps:\n" " grow:\n" " fuzz:\n" +" snapfb\n" " --\n" " threads\n" -" rfbwait:\n" " --\n" " progressive:\n" "\"\n" @@ -335,8 +339,7 @@ "remote control commands. See \\\"Help -> all\\\" for much info about x11vnc.\n" "\n" "Most menu items have a (?) button one can click on to get more information\n" -"about the option or command. In most cases it will be text extracted\n" -"from that in \\\"Help -> all\\\".\n" +"about the option or command.\n" "\n" "There are two states tkx11vnc can be in:\n" "\n" @@ -469,7 +472,7 @@ "\n" "proc textwin {name title text} {\n" " global max_text_height max_text_width\n" -" global bfont\n" +" global bfont ffont\n" "\n" " set width [textwidth $text]\n" " incr width\n" @@ -487,9 +490,11 @@ " frame $w.f -bd 0;\n" " pack $w.f -fill both -expand 1\n" " text $w.f.t -width $width -height $height -setgrid 1 -bd 2 \\\n" -" -yscrollcommand \"$w.f.y set\" -relief ridge -font fixed;\n" +" -yscrollcommand \"$w.f.y set\" -relief ridge \\\n" +" -font $ffont;\n" " scrollbar $w.f.y -orient v -relief sunken -command \"$w.f.t yview\";\n" -" button $w.f.b -text \"Dismiss\" -command \"destroy $w\" -font $bfont\n" +" button $w.f.b -text \"Dismiss\" -command \"destroy $w\" -font $bfont \\\n" +" -pady 2\n" "\n" " $w.f.t insert 1.0 $text;\n" "\n" @@ -915,121 +920,6 @@ "\n" "# Utilities for remote control and updating vars.\n" "\n" -"proc push_new_value0 {item name new {query 1}} {\n" -" # old way w/o -sync\n" -" global menu_var always_update remote_output query_output\n" -" global delay_sleep extra_sleep extra_sleep_split\n" -"\n" -" set debug [in_debug_mode]\n" -" set do_query_all 0\n" -" set getout 0\n" -"\n" -" if {$item == \"remote-cmd\"} {\n" -" # kludge for arbitrary remote command:\n" -" if {[regexp {^Q:} $new]} {\n" -" # extra kludge for Q:var to mean -Q var\n" -" regsub {^Q:} $new \"\" new\n" -" set qonly 1\n" -" } else {\n" -" set qonly 0\n" -" }\n" -" # need to extract item from new:\n" -" set qtmp $new\n" -" regsub {:.*$} $qtmp \"\" qtmp\n" -" if {! $qonly} {\n" -" set rargs [list \"-R\" \"$new\"]\n" -" set qargs [list \"-Q\" \"$qtmp\"]\n" -" set getout 1\n" -" } else {\n" -" set rargs [list \"-Q\" \"$qtmp\"]\n" -" set qargs [list \"-Q\" \"$qtmp\"]\n" -" }\n" -"\n" -" } elseif {[value_is_string $item]} {\n" -" set rargs [list \"-R\" \"$name:$new\"]\n" -" set qargs [list \"-Q\" \"$name\"]\n" -" } else {\n" -" set rargs [list \"-R\" \"$name\"]\n" -" set qargs [list \"-Q\" \"$name\"]\n" -" }\n" -"\n" -" if {!$debug} {\n" -" append_text \"x11vnc $rargs ...\"\n" -" }\n" -" set remote_output [run_remote_cmd $rargs]\n" -"\n" -" if {[lindex $rargs 0] == \"-Q\"} {\n" -" append_text \"\\t$remote_output\"\n" -" set getout 1\n" -" } elseif {! $query && ! $always_update} {\n" -" set getout 1\n" -" } elseif {$item == \"noremote\"} {\n" -" set getout 1\n" -" } elseif {[is_action $item] && ![opt_match Q $item] && $rargs != \"\"} {\n" -" set getout 1\n" -" } elseif {[regexp {^(sid|id)$} $item] && ![regexp {^0x} $new]} {\n" -" set getout 1\n" -" }\n" -"\n" -" if {$getout} {\n" -" append_text \"\\n\"\n" -" return\n" -" }\n" -"\n" -" stop_watch on\n" -" after $delay_sleep\n" -" if {[opt_match D $item]} {\n" -" set s [expr $extra_sleep/$extra_sleep_split] \n" -" append_text \" \"\n" -" for {set i 0} {$i<$extra_sleep_split} {incr i} {\n" -" after $s\n" -" append_text \".\"\n" -" update\n" -" }\n" -" }\n" -" stop_watch off\n" -"\n" -" if {!$debug} {\n" -" append_text \", -Q ...\"\n" -" }\n" -"\n" -" if {$item == \"disconnect\"} {\n" -" set new \"N/A\"\n" -" set do_query_all 1\n" -" }\n" -"\n" -" if {$always_update || $do_query_all} {\n" -" set query [query_all 1]\n" -" } else {\n" -" set query [run_remote_cmd $qargs]\n" -" }\n" -" set query_output $query\n" -"\n" -" if {![see_if_ok $query $item \"$name:$new\"]} {\n" -" # failed\n" -" if {[regexp {^a..=} $query]} {\n" -" # but some result came back\n" -" if {! $always_update} {\n" -" # synchronize everything\n" -" set query_output [query_all 1]\n" -" }\n" -" } else {\n" -" # server may be dead\n" -" if {$item != \"ping\" && $item != \"attach\"} {\n" -" try_connect\n" -" }\n" -" }\n" -" } else {\n" -" # succeeded\n" -" if {! $always_update} {\n" -" # synchronize this variable\n" -" update_menu_vars $query\n" -" } else {\n" -" # already done in query_all\n" -" }\n" -" }\n" -"}\n" -"\n" "proc push_new_value {item name new {query 1}} {\n" " global menu_var always_update remote_output query_output\n" " global delay_sleep extra_sleep extra_sleep_split\n" @@ -1270,6 +1160,25 @@ " } else {\n" " set msg $found\n" " }\n" +" if {!$ok && $found != \"\"} {\n" +" # check for floating point match:\n" +" set v1 \"\"\n" +" set v2 \"\"\n" +" regexp {:([0-9.][0-9.]*)$} $found m0 v1\n" +" regexp {:([0-9.][0-9.]*)$} $expected m0 v2\n" +" if {$v1 != \"\" && $v2 != \"\"} {\n" +" set diff \"\"\n" +" catch {set diff [expr \"$v1 - $v2\"]}\n" +" if {$diff != \"\"} {\n" +" if {$diff < 0} {\n" +" set diff [expr \"0.0 - $diff\"]\n" +" }\n" +" if {$diff < 0.00001} {\n" +" set ok 1\n" +" }\n" +" }\n" +" }\n" +" }\n" " if {$ok} {\n" " append_text \"\\tSet OK ($msg)\\n\"\n" " return 1\n" @@ -1278,6 +1187,12 @@ " # e.g. blackout:+30x30+20+20\n" " append_text \"\\t($msg)\\n\"\n" " return 1\n" +" } elseif {[regexp {:[0-9]\\.[0-9]} $expected]} {\n" +" append_text \"\\t($msg)\\n\"\n" +" return 1\n" +" } elseif {$item == \"connect\" || $item == \"disconnect\"} {\n" +" append_text \"\\t($msg)\\n\"\n" +" return 1\n" " } else {\n" " append_text \"\\t*FAILED* $msg\\n\"\n" " return 0\n" @@ -1304,13 +1219,14 @@ " if {$val == \"N/A\"} {\n" " continue\n" " }\n" -" if {0 && $debug} {\n" -" puts \"setting menuvar: $item: $old -> $val\"\n" -" }\n" " set menu_var($item) $val\n" " }\n" " if {$item == \"clients\"} {\n" " update_clients_menu $val\n" +" } elseif {$item == \"display\"} {\n" +" set_x11_display $val\n" +" } elseif {$item == \"vncdisplay\"} {\n" +" set_vnc_display $val\n" " }\n" " }\n" " }\n" @@ -1335,6 +1251,7 @@ " }\n" " }\n" " }\n" +" append_text \"Cleared all settings.\\n\"\n" "}\n" "\n" "proc all_query_vars {} {\n" @@ -1819,10 +1736,10 @@ "}\n" "\n" "proc update_clients_menu {list} {\n" -" global item_cascade\n" +" global item_cascade ffont\n" " set subm $item_cascade(current);\n" " catch {destroy $subm}\n" -" menu $subm -tearoff 0\n" +" menu $subm -tearoff 0 -font $ffont\n" " $subm add command\n" " $subm add command -label \"refresh-list\" -command \"update_clients_and_repost\"\n" " $subm add separator\n" @@ -1872,14 +1789,14 @@ " global text_area\n" " global entry_box entry_str entry_set entry_label entry_ok entry_browse\n" " global entry_help entry_skip\n" -" global bfont\n" +" global bfont ffont\n" " global helptext helpremote helplabel\n" "\n" " set label_width 80\n" "\n" " set info_label .info\n" " label $info_label -textvariable info_str -bd 2 -relief groove \\\n" -" -anchor w -width $label_width\n" +" -anchor w -width $label_width -font $ffont\n" " pack $info_label -side top -fill x -expand 0\n" "\n" " # Extract the Rows:\n" @@ -1995,11 +1912,13 @@ " } elseif {$item == \"Quit\"} {\n" " # Quit item must shut us down:\n" " $m add command -label \"$item\" -underline 0 \\\n" +" -font $ffont \\\n" " -command {destroy .; exit 0}\n" "\n" " } elseif {$case == \"Help\"} {\n" " # Help is simple help:\n" " $m add command -label \"$item\" \\\n" +" -font $ffont \\\n" " -command \"menu_help $item\"\n" "\n" " } elseif {$item == \"current\"} {\n" @@ -2008,11 +1927,13 @@ " set item_cascade($item) $subm\n" " update_clients_menu \"\"\n" " $m add cascade -label \"$item\" \\\n" +" -font $ffont \\\n" " -menu $subm\n" "\n" " } elseif {[is_action $item]} {\n" " # Action\n" " $m add command -label \"$item\" \\\n" +" -font $ffont \\\n" " -command \"do_var $item\"\n" " set menu_var($item) \"\"; # for convenience\n" "\n" @@ -2021,19 +1942,22 @@ " if {[regexp -- {-C:(.*)} $item_opts($item) m0 m1]} {\n" " # Radiobutton select\n" " set subm $m.cascade$menu_count($case)\n" -" menu $subm -tearoff 0\n" +" menu $subm -tearoff 0 -font $ffont\n" " foreach val [split $m1 \",\"] {\n" " $subm add radiobutton -label \"$val\" \\\n" " -command \"do_var $item\" \\\n" " -value \"$val\" \\\n" +" -font $ffont \\\n" " -variable menu_var($item)\n" " }\n" " $m add cascade -label \"$item\" \\\n" +" -font $ffont \\\n" " -menu $subm\n" " set item_cascade($item) $subm\n" " } else {\n" " # Arbitrary_string\n" " $m add command -label \"$item\" \\\n" +" -font $ffont \\\n" " -command \"do_var $item\"\n" " }\n" " set mvar 1\n" @@ -2042,6 +1966,7 @@ " # Boolean\n" " $m add checkbutton -label \"$item\" \\\n" " -command \"do_var $item\" \\\n" +" -font $ffont \\\n" " -variable menu_var($item)\n" " set menu_var($item) 0\n" " }\n" @@ -2075,6 +2000,7 @@ " set str \"(?)\"\n" " }\n" " $m add command -label $str \\\n" +" -font $ffont \\\n" " -command \"menu_help $label\";\n" "\n" " if {$str == \"\"} {\n" @@ -2100,17 +2026,19 @@ " no_x11_display\n" "\n" " set lw [expr {$label_width / 2}]\n" -" label $df_x11 -textvariable x11_display -width $lw -anchor w\n" +" label $df_x11 -textvariable x11_display -width $lw -anchor w \\\n" +" -font $ffont\n" "\n" " set df_vnc \"$df.vdisplay\"\n" " no_vnc_display\n" -" label $df_vnc -textvariable vnc_display -width $lw -anchor w\n" +" label $df_vnc -textvariable vnc_display -width $lw -anchor w \\\n" +" -font $ffont\n" "\n" " pack $df_x11 $df_vnc -side left \n" " pack $df -side top -fill x\n" "\n" " # text area\n" -" text .text -height 11 -relief ridge\n" +" text .text -height 11 -relief ridge -font $ffont\n" " set text_area .text\n" " pack .text -side top -fill both -expand 1\n" "\n" @@ -2128,28 +2056,35 @@ "\n" " set entry_str \"Set... : \"\n" " set ef_entry \"$ef.entry\"\n" -" entry $ef_entry -relief sunken\n" +" entry $ef_entry -relief sunken -font $ffont\n" " bind $ef_entry {set entry_set 1}\n" " bind $ef_entry {set entry_set 0}\n" "\n" " # Entry OK button\n" +" set bpx \"1m\"\n" +" set bpy \"1\"\n" +" set hlt \"0\"\n" " set ef_ok \"$ef.ok\"\n" -" button $ef_ok -text OK -pady 1 -command {set entry_set 1} \\\n" +" button $ef_ok -text OK -pady $bpy -padx $bpx -command {set entry_set 1} \\\n" +" -highlightthickness $hlt \\\n" " -font $bfont\n" "\n" " # Entry Skip button\n" " set ef_skip \"$ef.skip\"\n" -" button $ef_skip -text Skip -pady 0 -command {set entry_set 0} \\\n" +" button $ef_skip -text Skip -pady $bpy -padx $bpx -command {set entry_set 0} \\\n" +" -highlightthickness $hlt \\\n" " -font $bfont\n" "\n" " # Entry Help button\n" " set ef_help \"$ef.help\"\n" -" button $ef_help -text Help -pady 0 -command \\\n" -" {menu_help $entry_dialog_item} -font $bfont\n" +" button $ef_help -text Help -pady $bpy -padx $bpx -command \\\n" +" {menu_help $entry_dialog_item} -font $bfont \\\n" +" -highlightthickness $hlt\n" "\n" " # Entry Browse button\n" " set ef_browse \"$ef.browse\"\n" -" button $ef_browse -text \"Browse...\" -pady 0 -font $bfont \\\n" +" button $ef_browse -text \"Browse...\" -pady $bpy -padx $bpx -font $bfont \\\n" +" -highlightthickness $hlt \\\n" " -command {entry_insert [tk_getOpenFile]} \n" "\n" " pack $ef_label -side left\n" @@ -2322,6 +2257,9 @@ " if {$item == \"id\"} {\n" " set saw_id 1\n" " }\n" +" if {$item == \"httpport\" && $menu_var($item) == \"0\"} {\n" +" continue\n" +" }\n" " if {$item == \"progressive\" && $menu_var($item) == \"0\"} {\n" " continue\n" " }\n" @@ -2525,7 +2463,7 @@ "global all_settings reply_xdisplay always_update\n" "global max_text_height max_text_width\n" "global menu_var unset_str menus_disabled\n" -"global bfont old_labels\n" +"global bfont ffont old_labels\n" "global connected_to_x11vnc\n" "global delay_sleep extra_sleep extra_sleep_split\n" "global cache_all_query_vars\n" @@ -2535,7 +2473,8 @@ "set menus_disabled 0\n" "set max_text_height 40\n" "set max_text_width 90\n" -"set bfont -adobe-helvetica-bold-r-*-*-*-120-*-*-*-*-*-*;\n" +"set bfont \"-adobe-helvetica-bold-r-*-*-*-120-*-*-*-*-*-*\"\n" +"set ffont \"fixed\"\n" "set help_indent 24;\n" "set reply_xdisplay \"\"\n" "set all_settings \"None so far.\"\n" diff --git a/x11vnc/x11vnc.1 b/x11vnc/x11vnc.1 index 05b076c..baca7ed 100644 --- a/x11vnc/x11vnc.1 +++ b/x11vnc/x11vnc.1 @@ -1,8 +1,8 @@ .\" This file was automatically generated from x11vnc -help output. -.TH X11VNC "1" "December 2004" "x11vnc " "User Commands" +.TH X11VNC "1" "January 2005" "x11vnc " "User Commands" .SH NAME x11vnc - allow VNC connections to real X11 displays - version: 0.7.1pre, lastmod: 2004-12-27 + version: 0.7.1pre, lastmod: 2005-01-16 .SH SYNOPSIS .B x11vnc [OPTION]... @@ -57,7 +57,7 @@ environment variable to \fIdisp\fR. \fB-auth\fR \fIfile\fR .IP Set the X authority file to be \fIfile\fR, equivalent to -setting the XAUTHORITY environment varirable to \fIfile\fR +setting the XAUTHORITY environment variable to \fIfile\fR before startup. See .IR Xsecurity (7) , @@ -407,7 +407,8 @@ to handle all subsequent resizes (e.g. under \fB-xrandr,\fR \fB-o\fR \fIlogfile\fR .IP Write stderr messages to file \fIlogfile\fR instead of -to the terminal. Same as "\fB-logfile\fR \fIfile\fR". +to the terminal. Same as "\fB-logfile\fR \fIfile\fR". To append +to the file use "\fB-oa\fR \fIfile\fR" or "\fB-logappend\fR \fIfile\fR". .PP \fB-rc\fR \fIfilename\fR .IP @@ -623,7 +624,7 @@ cursors with transparency will not be displayed exactly for cursors that have transparency ("alpha channel" with values ranging from 0 to 255) Any cursor pixel with alpha value less than n becomes completely transparent. -Otherwise the pixel is completely opaque. Default 255 +Otherwise the pixel is completely opaque. Default 240 .IP Note: the options \fB-alphacut,\fR \fB-alphafrac,\fR and \fB-alphafrac\fR may be removed if a more accurate internal method for @@ -646,6 +647,17 @@ black background). Specify this option to remove the alpha factor. (useful for light colored semi-transparent cursors). .PP +\fB-alphablend\fR +.IP +In XFIXES mode send cursor alpha channel data to +libvncserver. The blending effect will only be +visible in \fB-nocursorshape\fR mode or for clients with +cursorshapeupdates turned off. (However there is a +hack for 32bpp with depth 24, it uses the extra 8 bits +to store cursor transparency for use with a hacked +vncviewer that applies the transparency locally. +See the FAQ for more info). +.PP \fB-nocursorshape\fR .IP Do not use the TightVNC CursorShapeUpdates extension @@ -699,36 +711,59 @@ To include button events use "Button1", ... etc. .PP \fB-nodragging\fR .IP -Do not update the display during mouse dragging -events (mouse motion with a button held down). -Greatly improves response on slow setups, but you lose -all visual feedback for drags, text selection, and some -menu traversals. It overrides any \fB-pointer_mode\fR setting -(think of it as pointer_mode 0) +Do not update the display during mouse dragging events +(mouse button held down). Greatly improves response on +slow setups, but you lose all visual feedback for drags, +text selection, and some menu traversals. It overrides +any \fB-pointer_mode\fR setting .PP \fB-pointer_mode\fR \fIn\fR .IP -Various pointer update schemes. The problem is pointer -motion can cause rapid changes on the screen, e.g. a -window drag. Neither x11vnc's screen polling nor the +Various pointer motion update schemes. "\fB-pm\fR" is +an alias. The problem is pointer motion can cause +rapid changes on the screen: consider the rapid changes +when you drag a large window around. Neither x11vnc's +screen polling and vnc compression routines nor the bandwidth to the vncviewers can keep up these rapid -screen changes: everything bogs down when dragging -or scrolling. Note that most video h/w is optimized -for writing, not reading (a 50X rate difference is -possible) and x11vnc is reading all the time. So a -scheme has to be used to "eat" much of that pointer -input before re-polling the screen. n can be 1 to 4. -.IP -n=1 was the original scheme used to about Jan 2004: it -basically just skips \fB-input_skip\fR pointer events before -repolling the screen. n=2 is an improved scheme: -by watching the current rate it tries to detect if -it should try to "eat" more pointer events. n=3 is -basically a dynamic \fB-nodragging\fR mode: it detects if the -mouse drag motion has paused and refreshes the display. -n=4 is TBD, it will try measure screen read and client -write rates and try to insert "frames" between the -on/off states of mode 3. The default n is 2. +screen changes: everything will bog down when dragging +or scrolling. So a scheme has to be used to "eat" +much of that pointer input before re-polling the screen +and sending out framebuffer updates. The mode number +\fIn\fR can be 0 to 4 and selects one of the schemes +desribed below. +.IP +n=0: does the same as \fB-nodragging.\fR (all screen polling +is suspended if a mouse button is pressed.) +.IP +n=1: was the original scheme used to about Jan 2004: +it basically just skips \fB-input_skip\fR keyboard or pointer +events before repolling the screen. +.IP +n=2 is an improved scheme: by watching the current rate +of input events it tries to detect if it should try to +"eat" additional pointer events before continuing. +.IP +n=3 is basically a dynamic \fB-nodragging\fR mode: it detects +when the mouse motion has paused and then refreshes +the display. +.IP +n=4: attempts to measures network rates and latency, +the video card read rate, and how many tiles have been +changed on the screen. From this, it aggressively tries +to push screen "frames" when it decides it has enough +resources to do so. NOT FINISHED. +.IP +The default n is 2. Note that modes 2, 3, 4 will skip +\fB-input_skip\fR keyboard events (but it will not count +pointer events). Also note that these modes are not +available in \fB-threads\fR mode which has its own pointer +event handling mechanism. +.IP +To try out the different pointer modes to see +which one gives the best response for your usage, +it is convenient to use the remote control function, +e.g. "x11vnc \fB-R\fR pointer_mode:4" or the tcl/tk gui +(Tuning -> pointer_mode -> n). .PP \fB-input_skip\fR \fIn\fR .IP @@ -737,6 +772,32 @@ read n user input events before scanning display. n < 0 means to act as though there is always user input. Default: 10 .PP +\fB-speeds\fR \fIrd,bw,lat\fR +.IP +x11vnc tries to estimate some speed parameters that +are used to optimize scheduling (e.g. \fB-pointer_mode\fR +4) and other things. Use the \fB-speeds\fR option to set +these manually. The triple \fIrd,bw,lat\fR corresponds +to video h/w read rate in MB/sec, network bandwidth to +clients in KB/sec, and network latency to clients in +milliseconds, respectively. If a value is left blank, +e.g. "\fB-speeds\fR \fI,100,15\fR", then the internal scheme is +used to estimate the empty value(s). +.IP +Typical PC video cards have read rates of 5-10 MB/sec. +If the framebuffer is in main memory instead of video +h/w (e.g. SunRay, shadowfb, Xvfb), the read rate may +be much faster. "x11perf \fB-getimage500"\fR can be used +to get a lower bound (remember to factor in the bytes +per pixel). It is up to you to estimate the network +bandwith to clients. For the latency the +.IR ping (1) +command can be used. +.IP +For convenience there are some aliases provided, +e.g. "\fB-speeds\fR \fImodem\fR". The aliases are: "modem" for +6,4,200; "dsl" for 6,100,50; and "lan" for 6,5000,1 +.PP \fB-debug_pointer\fR .IP Print debugging output for every pointer event. @@ -803,6 +864,22 @@ by checking the tile near the boundary. Default: 3 Tolerance in pixels to mark a tiles edges as changed. Default: 2 .PP +\fB-snapfb\fR +.IP +Instead of polling the X display framebuffer (fb) for +changes, periodically copy all of X display fb into main +memory and examine that copy for changes. Under some +circumstances this will improve interactive response, +or at least make things look smoother, but in others +(many) it will make the response worse. If the video +h/w fb is such that reading small tiles is very slow +this mode could help. To keep the "framerate" up +the screen size x bpp cannot be too large. Note that +this mode is very wasteful of memory I/O resources +(it makes full screen copies even if nothing changes). +It may be of use in video capture-like applications, +or where window tearing is a problem. +.PP \fB-gui\fR \fI[gui-opts]\fR .IP Start up a simple tcl/tk gui based on the the remote @@ -1073,6 +1150,10 @@ alpharemove enable \fB-alpharemove\fR mode. .IP noalpharemove disable \fB-alpharemove\fR mode. .IP +alphablend enable \fB-alphablend\fR mode. +.IP +noalphablend disable \fB-alphablend\fR mode. +.IP cursorshape disable \fB-nocursorshape\fR mode. .IP nocursorshape enable \fB-nocursorshape\fR mode. @@ -1091,9 +1172,11 @@ dragging disable \fB-nodragging\fR mode. .IP nodragging enable \fB-nodragging\fR mode. .IP -pointer_mode n set \fB-pointer_mode\fR to n. +pointer_mode:n set \fB-pointer_mode\fR to n. same as "pm" +.IP +input_skip:n set \fB-input_skip\fR to n. .IP -input_skip n set \fB-input_skip\fR to n. +speeds:str set \fB-speeds\fR to str. .IP debug_pointer enable \fB-debug_pointer,\fR same as "dp" .IP @@ -1123,6 +1206,10 @@ grow:n set \fB-grow\fR to n. .IP fuzz:n set \fB-fuzz\fR to n. .IP +snapfb enable \fB-snapfb\fR mode. +.IP +nosnapfb disable \fB-snapfb\fR mode. +.IP progressive:n set libvncserver \fB-progressive\fR slice height parameter to n. .IP @@ -1215,29 +1302,30 @@ the returned value corresponds to (hint: the ext_* variables correspond to the presence of X extensions): .IP ans= stop quit exit shutdown ping blacken zero -refresh reset close disconnect id sid flashcmap -noflashcmap truecolor notruecolor overlay nooverlay -overlay_cursor overlay_yescursor nooverlay_nocursor -nooverlay_cursor nooverlay_yescursor overlay_nocursor -visual scale viewonly noviewonly shared noshared -forever noforever once deny lock nodeny unlock -connect allowonce allow localhost nolocalhost accept -gone shm noshm flipbyteorder noflipbyteorder onetile -noonetile blackout xinerama noxinerama xrandr noxrandr -xrandr_mode padgeom quiet q noquiet modtweak nomodtweak -xkb noxkb skip_keycodes add_keysyms noadd_keysyms -clear_mods noclear_mods clear_keys noclear_keys -remap repeat norepeat fb nofb bell nobell sel -nosel primary noprimary cursorshape nocursorshape +refresh reset close disconnect id sid waitmapped +nowaitmapped flashcmap noflashcmap truecolor notruecolor +overlay nooverlay overlay_cursor overlay_yescursor +nooverlay_nocursor nooverlay_cursor nooverlay_yescursor +overlay_nocursor visual scale viewonly noviewonly +shared noshared forever noforever once deny lock nodeny +unlock connect allowonce allow localhost nolocalhost +accept gone shm noshm flipbyteorder noflipbyteorder +onetile noonetile blackout xinerama noxinerama xrandr +noxrandr xrandr_mode padgeom quiet q noquiet modtweak +nomodtweak xkb noxkb skip_keycodes add_keysyms +noadd_keysyms clear_mods noclear_mods clear_keys +noclear_keys remap repeat norepeat fb nofb bell nobell +sel nosel primary noprimary cursorshape nocursorshape cursorpos nocursorpos cursor show_cursor noshow_cursor -nocursor xfixes noxfixes alphacut alphafrac alpharemove -noalpharemove xwarp xwarppointer noxwarp noxwarppointer -buttonmap dragging nodragging pointer_mode input_skip -debug_pointer dp nodebug_pointer nodp debug_keyboard -dk nodebug_keyboard nodk deferupdate defer wait -rfbwait nap nonap sb screen_blank fs gaps grow fuzz -progressive rfbport http nohttp httpport httpdir -enablehttpproxy noenablehttpproxy alwaysshared +nocursor xfixes noxfixes alphacut alphafrac +alpharemove noalpharemove alphablend noalphablend +xwarp xwarppointer noxwarp noxwarppointer buttonmap +dragging nodragging pointer_mode pm input_skip speeds +debug_pointer dp nodebug_pointer nodp debug_keyboard dk +nodebug_keyboard nodk deferupdate defer wait rfbwait +nap nonap sb screen_blank fs gaps grow fuzz snapfb +nosnapfb progressive rfbport http nohttp httpport +httpdir enablehttpproxy noenablehttpproxy alwaysshared noalwaysshared nevershared noalwaysshared dontdisconnect nodontdisconnect desktop noremote .IP diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c index d556e97..43c6ea5 100644 --- a/x11vnc/x11vnc.c +++ b/x11vnc/x11vnc.c @@ -248,12 +248,14 @@ int overlay_present = 0; static int xrandr_base_event_type; #endif +#define CURSOR_TRANSPARENCY 1 int xfixes_present = 0; int use_xfixes = 1; int got_xfixes_cursor_notify = 0; -int alpha_threshold = 255; +int alpha_threshold = 240; double alpha_frac = 0.33; int alpha_remove = 0; +int alpha_blend = 0; #if LIBVNCSERVER_HAVE_LIBXFIXES #include @@ -267,7 +269,7 @@ static int xdamage_base_event_type; #endif /* date +'lastmod: %Y-%m-%d' */ -char lastmod[] = "0.7.1pre lastmod: 2004-12-27"; +char lastmod[] = "0.7.1pre lastmod: 2005-01-16"; /* X display info */ @@ -287,6 +289,8 @@ XImage *scanline; XImage *fullscreen; XImage **tile_row; /* for all possible row runs */ XImage *fb0; +XImage *snaprect = NULL; /* for XShmGetImage (fs_factor) */ +XImage *snap = NULL; /* the full snap fb */ #if !LIBVNCSERVER_HAVE_XSHM /* @@ -302,6 +306,7 @@ typedef struct { XShmSegmentInfo scanline_shm; XShmSegmentInfo fullscreen_shm; XShmSegmentInfo *tile_row_shm; /* for all possible row runs */ +XShmSegmentInfo snaprect_shm; /* rfb screen info */ rfbScreenInfoPtr screen = NULL; @@ -310,6 +315,7 @@ char *http_dir = NULL; char vnc_desktop_name[256]; char *main_fb; /* our copy of the X11 fb */ char *rfb_fb; /* same as main_fb unless transformation */ +char *snap_fb = NULL; /* used under -snapfb */ char *fake_fb = NULL; /* used under -padgeom */ int rfb_bytes_per_line; int main_bytes_per_line; @@ -318,6 +324,7 @@ unsigned short main_red_max, main_green_max, main_blue_max; unsigned short main_red_shift, main_green_shift, main_blue_shift; /* we now have a struct with client specific data: */ +#define RATE_SAMPLES 5 typedef struct _ClientData { int had_cursor_shape_updates; int had_cursor_pos_updates; @@ -325,6 +332,14 @@ typedef struct _ClientData { int client_port; int server_port; char *server_ip; + double timer; + double send_cmp_rate; + double send_raw_rate; + int set_cmp_bytes; + int set_raw_bytes; + double cmp_samp[RATE_SAMPLES]; + double raw_samp[RATE_SAMPLES]; + int sample; } ClientData; /* scaling parameters */ @@ -344,7 +359,7 @@ int tile_y = 32; int ntiles, ntiles_x, ntiles_y; /* arrays that indicate changed or checked tiles. */ -unsigned char *tile_has_diff, *tile_tried; +unsigned char *tile_has_diff, *tile_tried, *tile_copied; /* times of recent events */ time_t last_event, last_input, last_client = 0; @@ -373,6 +388,8 @@ char *program_cmdline = NULL; char vnc_connect_str[VNC_CONNECT_MAX+1]; Atom vnc_connect_prop = None; +struct utsname UT; + /* function prototypes (see filename comment above) */ int all_clients_initialized(void); @@ -410,6 +427,7 @@ void initialize_screen(int *argc, char **argv, XImage *fb); void initialize_polling_images(void); void initialize_signals(void); void initialize_tiles(void); +void initialize_speeds(void); void free_tiles(void); void initialize_watch_bell(void); void initialize_xinerama(void); @@ -446,16 +464,18 @@ void set_vnc_connect_prop(char *); char *process_remote_cmd(char *, int); void rfbPE(rfbScreenInfoPtr, long); void rfbCFD(rfbScreenInfoPtr, long); -int scan_for_updates(void); +int scan_for_updates(int); void set_colormap(int); void set_offset(void); void set_rfb_cursor(int); void set_visual(char *vstring); void set_cursor(int, int, int); void setup_cursors(void); +void setup_cursors_and_push(void); void first_cursor(void); void set_no_cursor(void); void set_cursor_was_changed(rfbScreenInfoPtr); +void set_cursor_was_moved(rfbScreenInfoPtr); int get_which_cursor(void); int get_xfixes_cursor(int); @@ -470,6 +490,14 @@ void check_x11_pointer(void); void check_bell_event(void); void check_xevents(void); char *this_host(void); +void set_vnc_desktop_name(void); + +int get_cmp_rate(void); +int get_raw_rate(void); +int get_read_rate(void); +int get_net_rate(void); +int get_net_latency(void); +void measure_send_rates(int); int get_remote_port(int sock); int get_local_port(int sock); @@ -491,8 +519,16 @@ char *use_dpy = NULL; char *auth_file = NULL; char *visual_str = NULL; char *logfile = NULL; +int logfile_append = 0; char *passwdfile = NULL; -char *blackout_string = NULL; +char *blackout_str = NULL; + +char *speeds_str = NULL; +int measure_speeds = 1; +int speeds_net_rate = 0; +int speeds_net_latency = 0; +int speeds_read_rate = 0; + char *rc_rcfile = NULL; int rc_norc = 0; int opts_bg = 0; @@ -519,6 +555,7 @@ int clear_mods = 0; /* -clear_mods (1) and -clear_keys (2) */ int nofb = 0; /* do not send any fb updates */ unsigned long subwin = 0x0; /* -id, -sid */ +int subwin_wait_mapped = 0; int xinerama = 0; /* -xinerama */ int xrandr = 0; /* -xrandr */ @@ -531,6 +568,7 @@ Time xrandr_cfg_time = 0; char *xrandr_mode = NULL; char *pad_geometry = NULL; time_t pad_geometry_time; +int use_snapfb = 0; char *client_connect = NULL; /* strings for -connect option */ char *client_connect_file = NULL; @@ -554,7 +592,9 @@ int add_keysyms = 0; /* automatically add keysyms to X server */ char *remap_file = NULL; /* -remap */ char *pointer_remap = NULL; -int pointer_mode = 2; /* use the various ways of updating pointer */ +/* use the various ways of updating pointer */ +#define POINTER_MODE_DEFAULT 2 +int pointer_mode = POINTER_MODE_DEFAULT; int pointer_mode_max = 4; int single_copytile = 0; /* use the old way copy_tiles() */ int single_copytile_orig = 0; @@ -930,6 +970,10 @@ int new_fb_size_clients(rfbScreenInfoPtr s) { rfbClientPtr cl; int count = 0; + if (! s) { + return 0; + } + iter = rfbGetClientIterator(s); while( (cl = rfbClientIteratorNext(iter)) ) { if (cl->useNewFBSize) { @@ -1097,6 +1141,35 @@ XImage *XCreateImage_wr(Display *disp, Visual *visual, unsigned int depth, width, height, bitmap_pad, bytes_per_line); } +void copy_image(XImage *dest, int x, int y, unsigned int w, unsigned int h) { + + /* default (w=0,h=0) is the fill the entire XImage */ + if (w < 1) { + w = dest->width; + } + if (h < 1) { + h = dest->height; + } + + if (use_snapfb && snap_fb && dest != snaprect) { + char *src, *dst; + int line, pixelsize = bpp/8; + + src = snap->data + snap->bytes_per_line*y + pixelsize*x; + dst = dest->data; + for (line = 0; line < h; line++) { + memcpy(dst, src, w * pixelsize); + src += snap->bytes_per_line; + dst += dest->bytes_per_line; + } + } else if (using_shm && w == dest->width && h == dest->height) { + XShmGetImage_wr(dpy, window, dest, x, y, AllPlanes); + } else { + XGetSubImage_wr(dpy, window, x, y, w, h, AllPlanes, + ZPixmap, dest, 0, 0); + } +} + /* * wrappers for XTestFakeKeyEvent, etc.. */ @@ -1210,9 +1283,11 @@ void clean_shm(int quick) { if (quick) { shm_delete(&scanline_shm); shm_delete(&fullscreen_shm); + shm_delete(&snaprect_shm); } else { shm_clean(&scanline_shm, scanline); shm_clean(&fullscreen_shm, fullscreen); + shm_clean(&snaprect_shm, snaprect); } /* @@ -1404,6 +1479,30 @@ int valid_window(Window win) { return ok; } +int wait_until_mapped(Window win) { + int ms = 50, waittime = 30; + time_t start = time(0); + XWindowAttributes attr; + + while (1) { + if (! valid_window(win)) { + if (time(0) > start + waittime) { + return 0; + } + usleep(ms * 1000); + continue; + } + if (! XGetWindowAttributes(dpy, win, &attr)) { + return 0; + } + if (attr.map_state == IsViewable) { + return 1; + } + usleep(ms * 1000); + } + return 0; +} + int get_window_size(Window win, int *x, int *y) { XWindowAttributes attr; /* valid_window? */ @@ -1461,6 +1560,10 @@ int all_clients_initialized(void) { rfbClientPtr cl; int ok = 1; + if (! screen) { + return ok; + } + iter = rfbGetClientIterator(screen); while( (cl = rfbClientIteratorNext(iter)) ) { if (cl->state != RFB_NORMAL) { @@ -1479,6 +1582,10 @@ char *list_clients(void) { char *list, tmp[32]; int count = 0; + if (!screen) { + return strdup(""); + } + iter = rfbGetClientIterator(screen); while( (cl = rfbClientIteratorNext(iter)) ) { count++; @@ -1487,7 +1594,7 @@ char *list_clients(void) { /* * each client: 123.123.123.123:60000/0x11111111-rw, = 36 bytes - * so count+1 * 100 should cover it. + * so count+1 * 100 must cover it. */ list = (char *) malloc((count+1)*100); @@ -1516,6 +1623,10 @@ void close_all_clients(void) { rfbClientIteratorPtr iter; rfbClientPtr cl; + if (! screen) { + return; + } + iter = rfbGetClientIterator(screen); while( (cl = rfbClientIteratorNext(iter)) ) { rfbCloseClient(cl); @@ -1534,6 +1645,10 @@ void close_clients(char *str) { return; } + if (! screen) { + return; + } + iter = rfbGetClientIterator(screen); while( (cl = rfbClientIteratorNext(iter)) ) { if (strstr(str, "0x")) { @@ -1554,7 +1669,7 @@ void close_clients(char *str) { char *rstr = str; if (! dotted_ip(str)) { rstr = host2ip(str); - if (rstr == NULL) { + if (rstr == NULL || *rstr == '\0') { if (host_warn++) { continue; } @@ -1738,23 +1853,23 @@ static int check_access(char *addr) { "blocked.\n"); return 0; } - - if (allow_list == NULL || *allow_list == '\0') { - if (allow_once == NULL) { - return 1; - } + if (addr == NULL || *addr == '\0') { + rfbLog("check_access: denying empty host IP address string.\n"); + return 0; } + if (allow_list == NULL) { + /* set to "" to possibly append allow_once */ allow_list = strdup(""); } - if (addr == NULL || *addr == '\0') { - rfbLog("check_access: denying empty host IP address string.\n"); - return 0; + if (*allow_list == '\0' && allow_once == NULL) { + /* no constraints, accept it */ + return 1; } if (strchr(allow_list, '/')) { /* a file of IP addresess or prefixes */ - int len; + int len, len2 = 0; struct stat sbuf; FILE *in; char line[1024], *q; @@ -1767,7 +1882,8 @@ static int check_access(char *addr) { } len = sbuf.st_size + 1; /* 1 more for '\0' at end */ if (allow_once) { - len += strlen(allow_once) + 2; + len2 = strlen(allow_once) + 2; + len += len2; } list = malloc(len); list[0] = '\0'; @@ -1782,20 +1898,22 @@ static int check_access(char *addr) { if ( (q = strchr(line, '#')) != NULL) { *q = '\0'; } - if (strlen(list) + strlen(line) >= len) { + if (strlen(list) + strlen(line) >= len - len2) { + /* file grew since our stat() */ break; } strcat(list, line); } fclose(in); if (allow_once) { + strcat(list, "\n"); strcat(list, allow_once); strcat(list, "\n"); } } else { - int len = strlen(allow_list); + int len = strlen(allow_list) + 1; if (allow_once) { - len += strlen(allow_once) + 2; + len += strlen(allow_once) + 1; } list = malloc(len); list[0] = '\0'; @@ -1813,28 +1931,43 @@ static int check_access(char *addr) { p = strtok(list, ", \t\n\r"); while (p) { - char *q, *r = NULL; + char *chk, *q, *r = NULL; if (*p == '\0') { p = strtok(NULL, ", \t\n\r"); continue; } if (! dotted_ip(p)) { r = host2ip(p); - if (r == NULL) { + if (r == NULL || *r == '\0') { rfbLog("check_access: bad lookup \"%s\"\n", p); p = strtok(NULL, ", \t\n\r"); continue; } rfbLog("check_access: lookup %s -> %s\n", p, r); - p = r; + chk = r; + } else { + chk = p; } - q = strstr(addr, p); - if (q == addr) { - rfbLog("check_access: client %s matches pattern %s\n", - addr, p); - allowed = 1; - } else if(!strcmp(p,"localhost") && !strcmp(addr,"127.0.0.1")) { + q = strstr(addr, chk); + if (chk[strlen(chk)-1] != '.') { + if (!strcmp(addr, chk)) { + if (chk != p) { + rfbLog("check_access: client %s " + "matches host %s=%s\n", addr, + chk, p); + } else { + rfbLog("check_access: client %s " + "matches host %s\n", addr, chk); + } + allowed = 1; + } else if(!strcmp(chk, "localhost") && + !strcmp(addr, "127.0.0.1")) { + allowed = 1; + } + } else if (q == addr) { + rfbLog("check_access: client %s matches pattern %s\n", + addr, chk); allowed = 1; } p = strtok(NULL, ", \t\n\r"); @@ -2449,6 +2582,10 @@ static int do_reverse_connect(char *str) { rfbLog("reverse_connect: string too long: %d bytes\n", len); return 0; } + if (!screen) { + rfbLog("reverse_connect: screen not setup yet.\n"); + return 0; + } /* copy in to host */ host = (char *) malloc((size_t) len+1); @@ -2634,6 +2771,7 @@ void check_connect_inputs(void) { */ enum rfbNewClientAction new_client(rfbClientPtr client) { ClientData *cd; + int i; last_event = last_input = time(0); if (inetd) { @@ -2692,6 +2830,12 @@ enum rfbNewClientAction new_client(rfbClientPtr client) { install_padded_fb(pad_geometry); } + for (i=0; icmp_samp[i] = 5000; /* 56k modem */ + cd->raw_samp[i] = 50000; + } + cd->sample = 0; + accepted_client = 1; last_client = time(0); @@ -4780,7 +4924,9 @@ void check_bell_event(void) { rfbLog("check_bell_event: not sending bell: " "uninitialized clients\n"); } else { - rfbSendBell(screen); + if (screen) { + rfbSendBell(screen); + } } } } @@ -4796,7 +4942,6 @@ int subwin_trap_count = 0; XErrorHandler old_getimage_handler; #define XRANDR_SET_TRAP_RET(x,y) \ if (subwin || xrandr) { \ - if (0) fprintf(stderr, " SET_TRAP: '%d' '%s'\n", x, y); \ trapped_getimage_xerror = 0; \ old_getimage_handler = XSetErrorHandler(trap_getimage_xerror); \ if (check_xrandr_event(y)) { \ @@ -4807,7 +4952,6 @@ XErrorHandler old_getimage_handler; } #define XRANDR_CHK_TRAP_RET(x,y) \ if (subwin || xrandr) { \ - if (0) fprintf(stderr, " CHK_TRAP: '%d' '%s'\n", x, y); \ if (trapped_getimage_xerror) { \ if (subwin) { \ static int last = 0; \ @@ -4926,7 +5070,7 @@ void handle_xrandr_change(int new_x, int new_y) { rfbLog(" shutting down due to XRANDR event.\n"); clean_up_exit(0); } - if (!strcmp(xrandr_mode, "newfbsize")) { + if (!strcmp(xrandr_mode, "newfbsize") && screen) { iter = rfbGetClientIterator(screen); while( (cl = rfbClientIteratorNext(iter)) ) { if (cl->useNewFBSize) { @@ -4958,7 +5102,6 @@ int check_xrandr_event(char *msg) { if (! xrandr || ! xrandr_present) { return 0; } - if (0) fprintf(stderr, "IN check_xrandr_event('%s')\n", msg); if (XCheckTypedEvent(dpy, xrandr_base_event_type + RRScreenChangeNotify, &xev)) { int do_change; @@ -5005,12 +5148,9 @@ int check_xrandr_event(char *msg) { XDisplayWidth(dpy, scr), XDisplayHeight(dpy, scr)); rfbLog("check_xrandr_event(): returning control to" " caller...\n"); - if (0) fprintf(stderr, "OUT-%d check_xrandr_event('%s')\n", - do_change, msg); return do_change; } #endif - if (0) fprintf(stderr, "OUT-0 check_xrandr_event('%s')\n", msg); return 0; } @@ -5055,7 +5195,7 @@ static Window selwin; /* special window for our selection */ * This is where we keep our selection: the string sent TO us from VNC * clients, and the string sent BY us to requesting X11 clients. */ -static char *xcut_string = NULL; +static char *xcut_str = NULL; /* * Our callbacks instruct us to check for changes in the cutbuffer @@ -5098,8 +5238,8 @@ static void selection_request(XEvent *ev) { } else { notify_event.property = req_event->property; } - if (xcut_string) { - length = strlen(xcut_string); + if (xcut_str) { + length = strlen(xcut_str); } else { length = 0; } @@ -5120,7 +5260,7 @@ static void selection_request(XEvent *ev) { } else { /* data request */ - data = (unsigned char *)xcut_string; + data = (unsigned char *)xcut_str; XChangeProperty(ev->xselectionrequest.display, ev->xselectionrequest.requestor, @@ -5188,6 +5328,9 @@ static void cutbuffer_send(void) { } /* now send it to any connected VNC clients (rfbServerCutText) */ + if (!screen) { + return; + } rfbSendServerCutText(screen, selection_str, strlen(selection_str)); } @@ -5281,6 +5424,9 @@ static void selection_send(XEvent *ev) { } /* now send it to any connected VNC clients (rfbServerCutText) */ + if (!screen) { + return; + } rfbSendServerCutText(screen, selection_str, newlen); } @@ -5339,7 +5485,7 @@ void check_xevents(void) { static int first = 1, sent_some_sel = 0; static time_t last_request = 0; time_t now = time(0); - int have_clients = screen->clientHead ? 1 : 0; + int have_clients = 0; if (first) { @@ -5347,6 +5493,9 @@ void check_xevents(void) { } first = 0; + if (screen && screen->clientHead) { + have_clients = 1; + } X_LOCK; /* * There is a bug where we have to wait before sending text to @@ -5457,9 +5606,9 @@ void check_xevents(void) { xev.xselectionclear.selection == XA_PRIMARY) { own_selection = 0; - if (xcut_string) { - free(xcut_string); - xcut_string = NULL; + if (xcut_str) { + free(xcut_str); + xcut_str = NULL; } } } @@ -5472,6 +5621,9 @@ void check_xevents(void) { */ void xcut_receive(char *text, int len, rfbClientPtr cl) { + if (!watch_selection) { + return; + } if (cl && cl->viewOnly) { return; } @@ -5490,13 +5642,13 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) { } /* duplicate the text string for our own use. */ - if (xcut_string != NULL) { - free(xcut_string); + if (xcut_str != NULL) { + free(xcut_str); } - xcut_string = (unsigned char *) + xcut_str = (unsigned char *) malloc((size_t) (len+1) * sizeof(unsigned char)); - strncpy(xcut_string, text, len); - xcut_string[len] = '\0'; /* make sure null terminated */ + strncpy(xcut_str, text, len); + xcut_str[len] = '\0'; /* make sure null terminated */ /* copy this text to CUT_BUFFER0 as well: */ XChangeProperty(dpy, rootwin, XA_CUT_BUFFER0, XA_STRING, 8, @@ -5549,6 +5701,10 @@ int send_remote_cmd(char *cmd, int query, int wait) { if (query || wait) { char line[VNC_CONNECT_MAX]; int rc=1, i=0, max=70, ms_sl=50; + + if (!strcmp(cmd, "cmd=stop")) { + max = 20; + } for (i=0; ihttpInitDone = FALSE; @@ -5815,7 +5980,7 @@ void reset_httpport(int old, int new) { } else if (inetd) { rfbLog("reset_httpport: cannot set httpport: %d" " in inetd.\n", hp); - } else { + } else if (screen) { screen->httpPort = hp; screen->httpInitDone = FALSE; if (screen->httpListenSock > -1) { @@ -5836,7 +6001,7 @@ void reset_rfbport(int old, int new) { } else if (inetd) { rfbLog("reset_rfbport: cannot set rfbport: %d" " in inetd.\n", rp); - } else { + } else if (screen) { rfbClientIteratorPtr iter; rfbClientPtr cl; int maxfd; @@ -5872,6 +6037,8 @@ void reset_rfbport(int old, int new) { rfbReleaseClientIterator(iter); screen->maxFd = maxfd; + + set_vnc_desktop_name(); } } @@ -6109,6 +6276,20 @@ char *process_remote_cmd(char *cmd, int stringonly) { do_new_fb(1); } } + } else if (strstr(p, "waitmapped") == p) { + if (query) { + snprintf(buf, bufn, "ans=%s:%d", p, + subwin_wait_mapped); + goto qry; + } + subwin_wait_mapped = 1; + } else if (strstr(p, "nowaitmapped") == p) { + if (query) { + snprintf(buf, bufn, "ans=%s:%d", p, + !subwin_wait_mapped); + goto qry; + } + subwin_wait_mapped = 0; } else if (!strcmp(p, "flashcmap")) { if (query) { @@ -6275,16 +6456,20 @@ char *process_remote_cmd(char *cmd, int stringonly) { } rfbLog("process_remote_cmd: enable sharing.\n"); shared = 1; - screen->alwaysShared = TRUE; - screen->neverShared = FALSE; + if (screen) { + screen->alwaysShared = TRUE; + screen->neverShared = FALSE; + } } else if (!strcmp(p, "noshared")) { if (query) { snprintf(buf, bufn, "ans=%s:%d", p, !shared); goto qry; } rfbLog("process_remote_cmd: disable sharing.\n"); shared = 0; - screen->alwaysShared = FALSE; - screen->neverShared = TRUE; + if (screen) { + screen->alwaysShared = FALSE; + screen->neverShared = TRUE; + } } else if (!strcmp(p, "forever")) { if (query) { @@ -6321,12 +6506,15 @@ char *process_remote_cmd(char *cmd, int stringonly) { COLON_CHECK("connect:") p += strlen("connect:"); /* this is a reverse connection */ - strncpy(vnc_connect_str, p, VNC_CONNECT_MAX); - vnc_connect_str[VNC_CONNECT_MAX] = '\0'; + reverse_connect(p); } else if (strstr(p, "allowonce") == p) { - NOTAPP COLON_CHECK("allowonce:") + if (query) { + snprintf(buf, bufn, "ans=%s%s%s", p, co, + NONUL(allow_once)); + goto qry; + } p += strlen("allowonce:"); allow_once = strdup(p); rfbLog("process_remote_cmd: set allow_once %s\n", allow_once); @@ -6536,30 +6724,30 @@ char *process_remote_cmd(char *cmd, int stringonly) { COLON_CHECK("blackout:") if (query) { snprintf(buf, bufn, "ans=%s%s%s", p, co, - NONUL(blackout_string)); + NONUL(blackout_str)); goto qry; } p += strlen("blackout:"); - if (blackout_string) { - before = strdup(blackout_string); + if (blackout_str) { + before = strdup(blackout_str); } else { before = strdup(""); } - old = blackout_string; + old = blackout_str; if (*p == '+') { p++; - blackout_string = add_item(blackout_string, p); + blackout_str = add_item(blackout_str, p); } else if (*p == '-') { p++; - blackout_string = delete_item(blackout_string, p); + blackout_str = delete_item(blackout_str, p); } else { - blackout_string = strdup(p); + blackout_str = strdup(p); } - if (strcmp(before, blackout_string)) { + if (strcmp(before, blackout_str)) { rfbLog("process_remote_cmd: changing -blackout\n"); rfbLog(" from: %s\n", before); - rfbLog(" to: %s\n", blackout_string); - if (0 && !strcmp(blackout_string, "") && + rfbLog(" to: %s\n", blackout_str); + if (0 && !strcmp(blackout_str, "") && single_copytile_orig != single_copytile) { rfbLog("resetting single_copytile to: %d\n", single_copytile_orig); @@ -6978,6 +7166,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { set_no_cursor(); cursor_shape_updates = 1; restore_cursor_shape_updates(screen); + first_cursor(); } else if (!strcmp(p, "nocursorshape")) { int i, max = 5; if (query) { @@ -6995,6 +7184,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { } cursor_shape_updates = 0; disable_cursor_shape_updates(screen); + first_cursor(); } else if (!strcmp(p, "cursorpos")) { if (query) { @@ -7037,6 +7227,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { "to: %d\n", show_cursor); } initialize_cursors_mode(); + first_cursor(); } else if (!strcmp(p, "show_cursor")) { if (query) { @@ -7058,6 +7249,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { "to: %s\n", multiple_cursors_mode); } initialize_cursors_mode(); + first_cursor(); } else if (!strcmp(p, "noshow_cursor") || !strcmp(p, "nocursor")) { if (query) { snprintf(buf, bufn, "ans=%s:%d", p, !show_cursor); @@ -7069,6 +7261,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { rfbLog("process_remote_cmd: disabling show_cursor.\n"); show_cursor = 0; initialize_cursors_mode(); + first_cursor(); } else if (!strcmp(p, "xfixes")) { if (query) { @@ -7084,6 +7277,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { " (if supported).\n"); use_xfixes = 1; initialize_xfixes(); + first_cursor(); } else if (!strcmp(p, "noxfixes")) { if (query) { snprintf(buf, bufn, "ans=%s:%d", p, !use_xfixes); @@ -7097,6 +7291,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { rfbLog("process_remote_cmd: disabling -xfixes.\n"); use_xfixes = 0; initialize_xfixes(); + first_cursor(); } else if (strstr(p, "alphacut") == p) { int a; @@ -7118,8 +7313,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { " transparent cursors.\n"); } alpha_threshold = a; - setup_cursors(); - first_cursor(); + setup_cursors_and_push(); } } else if (strstr(p, "alphafrac") == p) { double a; @@ -7137,8 +7331,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { rfbLog("process_remote_cmd: setting alphafrac " "%f -> %f.\n", alpha_frac, a); alpha_frac = a; - setup_cursors(); - first_cursor(); + setup_cursors_and_push(); } } else if (strstr(p, "alpharemove") == p) { if (query) { @@ -7148,8 +7341,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { if (!alpha_remove) { rfbLog("process_remote_cmd: enable alpharemove\n"); alpha_remove = 1; - setup_cursors(); - first_cursor(); + setup_cursors_and_push(); } } else if (strstr(p, "noalpharemove") == p) { if (query) { @@ -7159,8 +7351,28 @@ char *process_remote_cmd(char *cmd, int stringonly) { if (alpha_remove) { rfbLog("process_remote_cmd: disable alpharemove\n"); alpha_remove = 0; - setup_cursors(); - first_cursor(); + setup_cursors_and_push(); + } + } else if (strstr(p, "alphablend") == p) { + if (query) { + snprintf(buf, bufn, "ans=%s:%d", p, alpha_blend); + goto qry; + } + if (!alpha_blend) { + rfbLog("process_remote_cmd: enable alphablend\n"); + alpha_remove = 0; + alpha_blend = 1; + setup_cursors_and_push(); + } + } else if (strstr(p, "noalphablend") == p) { + if (query) { + snprintf(buf, bufn, "ans=%s:%d", p, !alpha_blend); + goto qry; + } + if (alpha_blend) { + rfbLog("process_remote_cmd: disable alphablend\n"); + alpha_blend = 0; + setup_cursors_and_push(); } } else if (strstr(p, "xwarp") == p || strstr(p, "xwarppointer") == p) { @@ -7218,7 +7430,24 @@ char *process_remote_cmd(char *cmd, int stringonly) { } p += strlen("pointer_mode:"); pm = atoi(p); - if (pm < 1 || pm > pointer_mode_max) { + if (pm < 0 || pm > pointer_mode_max) { + rfbLog("process_remote_cmd: pointer_mode out of range:" + " 1-%d: %d\n", pointer_mode_max, pm); + } else { + rfbLog("process_remote_cmd: setting pointer_mode %d\n", + pm); + pointer_mode = pm; + } + } else if (strstr(p, "pm") == p) { + int pm; + COLON_CHECK("pm:") + if (query) { + snprintf(buf, bufn, "ans=%s%s%d", p, co, pointer_mode); + goto qry; + } + p += strlen("pm:"); + pm = atoi(p); + if (pm < 0 || pm > pointer_mode_max) { rfbLog("process_remote_cmd: pointer_mode out of range:" " 1-%d: %d\n", pointer_mode_max, pm); } else { @@ -7226,6 +7455,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { pm); pointer_mode = pm; } + } else if (strstr(p, "input_skip") == p) { int is; COLON_CHECK("input_skip:") @@ -7238,6 +7468,21 @@ char *process_remote_cmd(char *cmd, int stringonly) { rfbLog("process_remote_cmd: setting input_skip %d\n", is); ui_skip = is; + } else if (strstr(p, "speeds") == p) { + COLON_CHECK("speeds:") + if (query) { + snprintf(buf, bufn, "ans=%s%s%s", p, co, + NONUL(speeds_str)); + goto qry; + } + p += strlen("speeds:"); + if (speeds_str) free(speeds_str); + speeds_str = strdup(p); + + rfbLog("process_remote_cmd: setting -speeds to:\n" + "\t'%s'\n", p); + initialize_speeds(); + } else if (!strcmp(p, "debug_pointer") || !strcmp(p, "dp")) { if (query) { snprintf(buf, bufn, "ans=%s:%d", p, debug_pointer); @@ -7422,6 +7667,29 @@ char *process_remote_cmd(char *cmd, int stringonly) { tile_fuzz, f); grow_fill = f; + } else if (!strcmp(p, "snapfb")) { + int orig = use_snapfb; + if (query) { + snprintf(buf, bufn, "ans=%s:%d", p, use_snapfb); + goto qry; + } + rfbLog("process_remote_cmd: turning on snapfb mode.\n"); + use_snapfb = 1; + if (orig != use_snapfb) { + do_new_fb(1); + } + } else if (!strcmp(p, "nosnapfb")) { + int orig = use_snapfb; + if (query) { + snprintf(buf, bufn, "ans=%s:%d", p, !use_snapfb); + goto qry; + } + rfbLog("process_remote_cmd: turning off snapfb mode.\n"); + use_snapfb = 0; + if (orig != use_snapfb) { + do_new_fb(1); + } + } else if (strstr(p, "progressive") == p) { int f; COLON_CHECK("progressive:") @@ -7504,9 +7772,8 @@ char *process_remote_cmd(char *cmd, int stringonly) { free(http_dir); } http_dir = strdup(p); - if (*p == '\0') { - http_connections(0); - } else { + http_connections(0); + if (*p != '\0') { http_connections(1); } } @@ -8019,12 +8286,21 @@ enum cursor_names { #define CURS_MAX 32 static cursor_info_t *cursors[CURS_MAX]; +void setup_cursors_and_push(void) { + setup_cursors(); + first_cursor(); +} + void first_cursor(void) { + if (! screen) { + return; + } if (! show_cursor) { screen->cursor = NULL; } else { - /* just set it to the arrow for now. */ - set_rfb_cursor(CURS_ARROW); + got_xfixes_cursor_notify++; + set_rfb_cursor(get_which_cursor()); + set_cursor_was_changed(screen); } } @@ -8338,10 +8614,11 @@ int get_xfixes_cursor(int init) { int use, oldest, i, x, y, w, h, len; int Bpp = bpp/8; time_t oldtime, now; - char *bitmap, *rich; + char *bitmap, *rich, *alpha; unsigned long black, white; rfbCursorPtr c; int thresh, n_opaque, n_trans, n_alpha, histo[256]; + int send_alpha = 0, alpha_shift; XFixesCursorImage *xfc; if (! got_xfixes_cursor_notify) { @@ -8419,6 +8696,11 @@ int get_xfixes_cursor(int init) { if (cursors[use]->rfb->richSource) { free(cursors[use]->rfb->richSource); } +#if !OLD_TREE && CURSOR_TRANSPARENCY + if (cursors[use]->rfb->alphaSource) { + free(cursors[use]->rfb->alphaSource); + } +#endif if (cursors[use]->rfb->source) { free(cursors[use]->rfb->source); } @@ -8443,6 +8725,7 @@ int get_xfixes_cursor(int init) { /* for rich cursor pixel data */ rich = (char *)calloc(Bpp*len, 1); + alpha = (char *)calloc(1*len, 1); n_opaque = 0; n_trans = 0; @@ -8470,6 +8753,19 @@ int get_xfixes_cursor(int init) { i++; } } + if (alpha_blend) { + send_alpha = 0; +#if CURSOR_TRANSPARENCY + if (Bpp == 4) { + send_alpha = 1; + } +#endif + alpha_shift = 24; + if (main_red_shift == 24 || main_green_shift == 24 || + main_blue_shift == 24) { + alpha_shift = 0; /* XXX correct? */ + } + } if (n_opaque >= alpha_frac * n_alpha) { thresh = alpha_threshold; } else { @@ -8493,10 +8789,9 @@ int get_xfixes_cursor(int init) { a = 0xff000000 & (*(xfc->pixels+i)); a = a >> 24; /* alpha channel */ + if (a < thresh) { bitmap[i] = ' '; - i++; - continue; } else { bitmap[i] = 'x'; } @@ -8540,20 +8835,40 @@ int get_xfixes_cursor(int init) { ui |= (r << main_red_shift); ui |= (g << main_green_shift); ui |= (b << main_blue_shift); + if (send_alpha) { + ui |= (a << alpha_shift); + } } /* insert value into rich source: */ p = rich + Bpp*i; + +#if 0 + memcpy(p, (char *)&ui, Bpp); +#else if (Bpp == 1) { *((unsigned char *)p) = (unsigned char) ui; } else if (Bpp == 2) { *((unsigned short *)p) = (unsigned short) ui; + } else if (Bpp == 3) { + *((unsigned char *)p) + = (unsigned char) ((ui & 0x0000ff) >> 0); + *((unsigned char *)(p+1)) + = (unsigned char) ((ui & 0x00ff00) >> 8); + *((unsigned char *)(p+2)) + = (unsigned char) ((ui & 0xff0000) >> 16); } else if (Bpp == 4) { *((unsigned int *)p) = (unsigned int) ui; } +#endif + + /* insert alpha value into alpha source: */ + p = alpha + i; + *((unsigned char *)p) = (unsigned char) a; + i++; } } @@ -8571,6 +8886,15 @@ int get_xfixes_cursor(int init) { c->cleanupRichSource = FALSE; c->richSource = rich; +#if !OLD_TREE && CURSOR_TRANSPARENCY + if (alpha_blend && !indexed_color) { + c->alphaSource = alpha; + c->alphaPreMultiplied = TRUE; + } else { + c->alphaSource = NULL; + } +#endif + /* place cursor into our collection */ cursors[use]->rfb = c; @@ -8711,6 +9035,7 @@ int get_which_cursor(void) { Window r; trapped_xerror = 0; + X_LOCK; old_handler = XSetErrorHandler(trap_xerror); /* "narrow" windows are WM */ @@ -8721,6 +9046,7 @@ int get_which_cursor(void) { } } XSetErrorHandler(old_handler); + X_UNLOCK; trapped_xerror = 0; } if (which == which0) { @@ -8750,7 +9076,7 @@ void mark_cursor_patch_modified(rfbScreenInfoPtr s, int old) { int curx, cury, xhot, yhot, w, h; int x1, x2, y1, y2; - if (! s->cursor) { + if (! s || ! s->cursor) { return; } @@ -8785,6 +9111,9 @@ void set_cursor_was_changed(rfbScreenInfoPtr s) { rfbClientIteratorPtr iter; rfbClientPtr cl; + if (! s) { + return; + } iter = rfbGetClientIterator(s); while( (cl = rfbClientIteratorNext(iter)) ) { cl->cursorWasChanged = TRUE; @@ -8796,6 +9125,9 @@ void set_cursor_was_moved(rfbScreenInfoPtr s) { rfbClientIteratorPtr iter; rfbClientPtr cl; + if (! s) { + return; + } iter = rfbGetClientIterator(s); while( (cl = rfbClientIteratorNext(iter)) ) { cl->cursorWasMoved = TRUE; @@ -8808,6 +9140,9 @@ void restore_cursor_shape_updates(rfbScreenInfoPtr s) { rfbClientPtr cl; int count = 0; + if (! s || ! s->clientHead) { + return; + } iter = rfbGetClientIterator(s); while( (cl = rfbClientIteratorNext(iter)) ) { int changed = 0; @@ -8837,6 +9172,10 @@ void disable_cursor_shape_updates(rfbScreenInfoPtr s) { rfbClientIteratorPtr iter; rfbClientPtr cl; + if (! s || ! s->clientHead) { + return; + } + iter = rfbGetClientIterator(s); while( (cl = rfbClientIteratorNext(iter)) ) { ClientData *cd; @@ -8861,6 +9200,9 @@ int cursor_shape_updates_clients(rfbScreenInfoPtr s) { rfbClientPtr cl; int count = 0; + if (! s) { + return 0; + } iter = rfbGetClientIterator(s); while( (cl = rfbClientIteratorNext(iter)) ) { if (cl->enableCursorShapeUpdates) { @@ -8876,6 +9218,9 @@ int cursor_pos_updates_clients(rfbScreenInfoPtr s) { rfbClientPtr cl; int count = 0; + if (! s) { + return 0; + } iter = rfbGetClientIterator(s); while( (cl = rfbClientIteratorNext(iter)) ) { if (cl->enableCursorPosUpdates) { @@ -8898,6 +9243,9 @@ void cursor_position(int x, int y) { int x_old, y_old, x_in = x, y_in = y; /* x and y are current positions of X11 pointer on the X11 display */ + if (!screen) { + return; + } if (scaling) { x = ((double) x / dpy_x) * scaled_x; @@ -8978,6 +9326,9 @@ void set_rfb_cursor(int which) { if (! show_cursor) { return; } + if (! screen) { + return; + } if (workaround && screen->cursor) { int all_are_cursor_pos = 1; @@ -9415,6 +9766,15 @@ void install_padded_fb(char *geom) { pad_geometry_time = time(0); } +void initialize_snap_fb(void) { + if (snap_fb) { + free(snap_fb); + } + snap = XGetImage_wr(dpy, window, 0, 0, dpy_x, dpy_y, AllPlanes, + ZPixmap); + snap_fb = snap->data; +} + /* * initialize a fb for the X display */ @@ -9426,10 +9786,15 @@ XImage *initialize_xdisplay_fb(void) { int subwin_bs; X_LOCK; - if (subwin && !valid_window((Window) subwin)) { - rfbLog("invalid sub-window: 0x%lx\n", subwin); - X_UNLOCK; - clean_up_exit(1); + if (subwin) { + if (subwin_wait_mapped) { + wait_until_mapped(subwin); + } + if (!valid_window((Window) subwin)) { + rfbLog("invalid sub-window: 0x%lx\n", subwin); + X_UNLOCK; + clean_up_exit(1); + } } if (overlay) { @@ -9638,6 +10003,9 @@ XImage *initialize_xdisplay_fb(void) { usleep(250 * 1000); goto again; } + if (use_snapfb) { + initialize_snap_fb(); + } X_UNLOCK; if (fb->bits_per_pixel == 24 && ! quiet) { @@ -10080,8 +10448,7 @@ void initialize_screen(int *argc, char **argv, XImage *fb) { bpp = screen->serverFormat.bitsPerPixel; depth = screen->serverFormat.depth; - setup_cursors(); - first_cursor(); + setup_cursors_and_push(); if (scaling) { mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0); @@ -10150,9 +10517,7 @@ void initialize_screen(int *argc, char **argv, XImage *fb) { screen->newClientHook = new_client; screen->kbdAddEvent = keyboard; screen->ptrAddEvent = pointer; - if (watch_selection) { - screen->setXCutText = xcut_receive; - } + screen->setXCutText = xcut_receive; rfbInitServer(screen); @@ -10464,7 +10829,7 @@ void initialize_xinerama (void) { /* max len is 10000x10000+10000+10000 (23 chars) per geometry */ rcnt = (int) sraRgnCountRects(black_region); - bstr = (char *) malloc(30 * rcnt * sizeof(char)); + bstr = (char *) malloc(30 * (rcnt+1) * sizeof(char)); tstr = (char *) malloc(30 * sizeof(char)); bstr[0] = '\0'; @@ -10498,8 +10863,8 @@ void initialize_xinerama (void) { } void initialize_blackouts_and_xinerama(void) { - if (blackout_string != NULL) { - initialize_blackouts(blackout_string); + if (blackout_str != NULL) { + initialize_blackouts(blackout_str); } if (xinerama) { initialize_xinerama(); @@ -10525,12 +10890,18 @@ void push_sleep(n) { * try to forcefully push a black screen to all connected clients */ void push_black_screen(int n) { + if (!screen) { + return; + } zero_fb(0, 0, dpy_x, dpy_y); mark_rect_as_modified(0, 0, dpy_x, dpy_y, 1); push_sleep(n); } void refresh_screen(void) { + if (!screen) { + return; + } mark_rect_as_modified(0, 0, dpy_x, dpy_y, 1); rfbPE(screen, -1); } @@ -10539,7 +10910,7 @@ void refresh_screen(void) { * Fill the framebuffer with zero for the prescribed rectangle */ void zero_fb(int x1, int y1, int x2, int y2) { - int pixelsize = bpp >> 3; + int pixelsize = bpp/8; int line, fill = 0; char *dst; @@ -10549,6 +10920,9 @@ void zero_fb(int x1, int y1, int x2, int y2) { if (y1 < 0 || y2 <= y1 || y2 > dpy_y) { return; } + if (! main_fb) { + return; + } dst = main_fb + y1 * main_bytes_per_line + x1 * pixelsize; line = y1; @@ -10607,6 +10981,8 @@ void initialize_tiles(void) { malloc((size_t) (ntiles * sizeof(unsigned char))); tile_tried = (unsigned char *) malloc((size_t) (ntiles * sizeof(unsigned char))); + tile_copied = (unsigned char *) + malloc((size_t) (ntiles * sizeof(unsigned char))); tile_blackout = (tile_blackout_t *) malloc((size_t) (ntiles * sizeof(tile_blackout_t))); tile_region = (region_t *) malloc((size_t) (ntiles * sizeof(region_t))); @@ -10629,6 +11005,10 @@ void free_tiles(void) { free(tile_tried); tile_tried = NULL; } + if (tile_copied) { + free(tile_copied); + tile_copied = NULL; + } if (tile_blackout) { free(tile_blackout); tile_blackout = NULL; @@ -10661,7 +11041,8 @@ static int fs_factor = 0; static void set_fs_factor(int max) { int f, fac = 1, n = dpy_y; - if ( (bpp/8) * dpy_x * dpy_y <= max ) { + fs_factor = 0; + if ((bpp/8) * dpy_x * dpy_y <= max) { fs_factor = 1; return; } @@ -10830,7 +11211,7 @@ void shm_clean(XShmSegmentInfo *shm, XImage *xim) { } void initialize_polling_images(void) { - int i; + int i, MB = 1024 * 1024; /* set all shm areas to "none" before trying to create any */ scanline_shm.shmid = -1; @@ -10839,6 +11220,9 @@ void initialize_polling_images(void) { fullscreen_shm.shmid = -1; fullscreen_shm.shmaddr = (char *) -1; fullscreen = NULL; + snaprect_shm.shmid = -1; + snaprect_shm.shmaddr = (char *) -1; + snaprect = NULL; for (i=1; i<=ntiles_x; i++) { tile_row_shm[i].shmid = -1; tile_row_shm[i].shmaddr = (char *) -1; @@ -10850,20 +11234,17 @@ void initialize_polling_images(void) { if (! shm_create(&scanline_shm, &scanline, dpy_x, 1, "scanline")) { clean_up_exit(1); } - if (0 && !quiet) { - if (using_shm) { - rfbLog("created \"scanline\" shm polling image.\n"); - } else { - rfbLog("created \"scanline\" polling image.\n"); - } - } /* * the fullscreen (e.g. 1280x1024/fs_factor) shared memory area image: * (we cut down the size of the shm area to try avoid and shm segment * limits, e.g. the default 1MB on Solaris) */ - set_fs_factor(1024 * 1024); + if (UT.sysname && strstr(UT.sysname, "Linux")) { + set_fs_factor(10 * MB); + } else { + set_fs_factor(1 * MB); + } if (fs_frac >= 1.0) { fs_frac = 1.1; fs_factor = 0; @@ -10875,13 +11256,15 @@ void initialize_polling_images(void) { dpy_y/fs_factor, "fullscreen")) { clean_up_exit(1); } - if (0 && !quiet) { - if (using_shm) { - rfbLog("created \"scanline\" shm polling image.\n"); - } else { - rfbLog("created \"scanline\" polling image.\n"); - } - } + } + if (use_snapfb) { + if (! fs_factor) { + rfbLog("warning: disabling -snapfb mode.\n"); + use_snapfb = 0; + } else if (! shm_create(&snaprect_shm, &snaprect, dpy_x, + dpy_y/fs_factor, "snaprect")) { + clean_up_exit(1); + } } /* @@ -11214,6 +11597,9 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) { */ shrink = 0; } + if (!screen || !rfb_fb || !main_fb) { + return; + } if (! screen->serverFormat.trueColour) { /* @@ -11579,7 +11965,7 @@ static int copy_tiles(int tx, int ty, int nt) { int size_x, size_y, width1, width2; int off, len, n, dw, dx, t; int w1, w2, dx1, dx2; /* tmps for normal and short tiles */ - int pixelsize = bpp >> 3; + int pixelsize = bpp/8; int first_min, last_max; char *src, *dst, *s_src, *s_dst, *m_src, *m_dst; @@ -11629,18 +12015,9 @@ static int copy_tiles(int tx, int ty, int nt) { X_LOCK; XRANDR_SET_TRAP_RET(-1, "copy_tile-set"); /* read in the whole tile run at once: */ - if (using_shm && size_x == tile_x * nt && size_y == tile_y) { - /* general case: */ - XShmGetImage_wr(dpy, window, tile_row[nt], x, y, AllPlanes); - } else { - /* - * No shm or near bottom/rhs edge case: - * (but only if tile size does not divide screen size) - */ - XGetSubImage_wr(dpy, window, x, y, size_x, size_y, AllPlanes, - ZPixmap, tile_row[nt], 0, 0); - } + copy_image(tile_row[nt], x, y, size_x, size_y); XRANDR_CHK_TRAP_RET(-1, "copy_tile-chk"); + X_UNLOCK; if (blackouts && tile_blackout[n].cover == 1) { @@ -11872,6 +12249,8 @@ static int copy_tiles(int tx, int ty, int nt) { tile_region[n+s].left_diff = left_diff[t]; tile_region[n+s].right_diff = right_diff[t]; + + tile_copied[n+s] = 1; } return(1); @@ -12043,15 +12422,42 @@ static int copy_tiles_backward_pass(void) { return diffs; } -static int gap_try(int x, int y, int *run, int *saw, int along_x) { - int n, m, i, xt, yt, ct; +static int copy_tiles_additional_pass(void) { + int x, y, n; + int diffs = 0, ct; - n = x + y * ntiles_x; + for (y=0; y < ntiles_y; y++) { + for (x=0; x < ntiles_x; x++) { + n = x + y * ntiles_x; /* number of this tile */ - if (! tile_has_diff[n]) { - if (*saw) { - (*run)++; /* extend the gap run. */ - } + if (! tile_has_diff[n]) { + continue; + } + if (tile_copied[n]) { + continue; + } + + ct = copy_tiles(x, y, 1); + if (ct < 0) return ct; /* fatal */ + } + } + for (n=0; n < ntiles; n++) { + if (tile_has_diff[n]) { + diffs++; + } + } + return diffs; +} + +static int gap_try(int x, int y, int *run, int *saw, int along_x) { + int n, m, i, xt, yt, ct; + + n = x + y * ntiles_x; + + if (! tile_has_diff[n]) { + if (*saw) { + (*run)++; /* extend the gap run. */ + } return 0; } if (! *saw || *run == 0 || *run > gaps_fill) { @@ -12204,7 +12610,7 @@ static void blackout_regions(void) { * are other issues... use -fs 1.0 to disable. */ int copy_screen(void) { - int pixelsize = bpp >> 3; + int pixelsize = bpp/8; char *fbp; int i, y, block_size; @@ -12214,6 +12620,9 @@ int copy_screen(void) { block_size = (dpy_x * (dpy_y/fs_factor) * pixelsize); + if (! main_fb) { + return 0; + } fbp = main_fb; y = 0; @@ -12222,15 +12631,9 @@ int copy_screen(void) { /* screen may be too big for 1 shm area, so broken into fs_factor */ for (i=0; i < fs_factor; i++) { XRANDR_SET_TRAP_RET(-1, "copy_screen-set"); - if (using_shm) { - XShmGetImage_wr(dpy, window, fullscreen, 0, y, - AllPlanes); - } else { - XGetSubImage_wr(dpy, window, 0, y, fullscreen->width, - fullscreen->height, AllPlanes, ZPixmap, fullscreen, - 0, 0); - } + copy_image(fullscreen, 0, y, 0, 0); XRANDR_CHK_TRAP_RET(-1, "copy_screen-chk"); + memcpy(fbp, fullscreen->data, (size_t) block_size); y += dpy_y / fs_factor; @@ -12247,6 +12650,50 @@ int copy_screen(void) { return 0; } +int copy_snap(void) { + int pixelsize = bpp/8; + char *fbp; + int i, y, block_size; + double dt = 0.0; + static int first = 1; + + if (! fs_factor) { + return 0; + } + + block_size = (dpy_x * (dpy_y/fs_factor) * pixelsize); + + if (! snap_fb || ! snap || ! snaprect) { + return 0; + } + fbp = snap_fb; + y = 0; + + dtime(&dt); + X_LOCK; + + /* screen may be too big for 1 shm area, so broken into fs_factor */ + for (i=0; i < fs_factor; i++) { + XRANDR_SET_TRAP_RET(-1, "copy_snap-set"); + copy_image(snaprect, 0, y, 0, 0); + XRANDR_CHK_TRAP_RET(-1, "copy_snap-chk"); + + memcpy(fbp, snaprect->data, (size_t) block_size); + + y += dpy_y / fs_factor; + fbp += block_size; + } + + X_UNLOCK; + dt = dtime(&dt); + if (first) { + rfbLog("copy_snap: time for -snapfb snapshot: %.3f sec\n", dt); + first = 0; + } + + return 0; +} + /* * Utilities for managing the "naps" to cut down on amount of polling. @@ -12473,25 +12920,24 @@ void set_offset(void) { */ static int scan_display(int ystart, int rescan) { char *src, *dst; - int pixelsize = bpp >> 3; + int pixelsize = bpp/8; int x, y, w, n; int tile_count = 0; int whole_line = 1, nodiffs = 0; y = ystart; + if (! main_fb) { + rfbLog("scan_display: no main_fb!\n"); + return 0; + } + while (y < dpy_y) { /* grab the horizontal scanline from the display: */ X_LOCK; XRANDR_SET_TRAP_RET(-1, "scan_display-set"); - if (using_shm) { - XShmGetImage_wr(dpy, window, scanline, 0, y, AllPlanes); - } else { - XGetSubImage_wr(dpy, window, 0, y, scanline->width, - scanline->height, AllPlanes, ZPixmap, scanline, - 0, 0); - } + copy_image(scanline, 0, y, 0, 0); XRANDR_CHK_TRAP_RET(-1, "scan_display-chk"); X_UNLOCK; @@ -12566,13 +13012,16 @@ static int scan_display(int ystart, int rescan) { * toplevel for the scanning, rescanning, and applying the heuristics. * returns number of changed tiles. */ -int scan_for_updates(void) { +int scan_for_updates(int count_only) { int i, tile_count, tile_diffs; + int old_copy_tile; double frac1 = 0.1; /* tweak parameter to try a 2nd scan_display() */ double frac2 = 0.35; /* or 3rd */ + double frac3 = 0.02; /* do scan_display() again after copy_tiles() */ for (i=0; i < ntiles; i++) { tile_has_diff[i] = 0; tile_tried[i] = 0; + tile_copied[i] = 0; } /* @@ -12580,17 +13029,19 @@ int scan_for_updates(void) { * tile_x = tile_y = NSCAN = 32! */ - scan_count++; - scan_count %= NSCAN; + if (!count_only) { + scan_count++; + scan_count %= NSCAN; - if (scan_count % (NSCAN/4) == 0) { - /* some periodic maintenance */ + if (scan_count % (NSCAN/4) == 0) { + /* some periodic maintenance */ - if (subwin) { - set_offset(); /* follow the subwindow */ - } - if (indexed_color) { /* check for changed colormap */ - set_colormap(0); + if (subwin) { + set_offset(); /* follow the subwindow */ + } + if (indexed_color) { /* check for changed colormap */ + set_colormap(0); + } } } @@ -12606,6 +13057,12 @@ int scan_for_updates(void) { tile_count = scan_display(scanlines[scan_count], 0); SCAN_FATAL(tile_count); + if (count_only) { + scan_in_progress = 0; + fb_copy_in_progress = 0; + return tile_count; + } + nap_set(tile_count); if (fs_factor && frac1 >= fs_frac) { @@ -12674,13 +13131,18 @@ int scan_for_updates(void) { /* * Old way, copy I/O one tile at a time. */ - tile_diffs = copy_all_tiles(); + old_copy_tile = 1; } else { /* * New way, does runs of horizontal tiles at once. * Note that below, for simplicity, the extra tile finding * (e.g. copy_tiles_backward_pass) is done the old way. */ + old_copy_tile = 0; + } + if (old_copy_tile) { + tile_diffs = copy_all_tiles(); + } else { tile_diffs = copy_all_tile_runs(); } SCAN_FATAL(tile_diffs); @@ -12692,6 +13154,22 @@ int scan_for_updates(void) { tile_diffs = copy_tiles_backward_pass(); SCAN_FATAL(tile_diffs); + if (tile_diffs > frac3 * ntiles) { + /* + * we spent a lot of time in those copy_tiles, run + * another scan, maybe more of the screen changed. + */ + int cp = (NSCAN - scan_count + 13) % NSCAN; + + scan_in_progress = 1; + tile_count = scan_display(scanlines[cp], 1); + SCAN_FATAL(tile_count); + scan_in_progress = 0; + + tile_diffs = copy_tiles_additional_pass(); + SCAN_FATAL(tile_diffs); + } + /* Given enough tile diffs, try the islands: */ if (grow_fill && tile_diffs > 4) { tile_diffs = grow_islands(); @@ -12753,7 +13231,7 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, pid_t parent) { char *wish = NULL, *orig_path, *full_path, *tpath, *p; int try_max = 4, sleep = 300; pid_t mypid = getpid(); - FILE *pipe; + FILE *pipe, *tmpf; if (*gui_code == '\0') { rfbLog("gui not available in this program.\n"); @@ -12822,7 +13300,8 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, pid_t parent) { char *wishes[] = {"wish", "wish8.3", "wish8.4"}; int nwishes = 3, i; - try = (char *)malloc(strlen(p) + 10); + /* strlen("wish8.4") is 7 */ + try = (char *)malloc(strlen(p) + 1 + 7 + 1); for (i=0; i quick_spin_fac * dt) { + /* get out if spin time comparable to last scan time */ + break; + } + if (got_pointer_input > g) { + g = got_pointer_input; + if (eaten++ < max_eat) { + continue; + } + } else { + miss++; + } + if (miss > 1) { /* 1 means out on 2nd miss */ + break; + } + } + + + /* + * Probably grinding with a lot of fb I/O if dt is this large. + * (need to do this more elegantly) + * + * Current idea is to spin our wheels here *not* processing any + * fb I/O, but still processing the user input. This user input + * goes to the X display and changes it, but we don't poll it + * while we "rest" here for a time on order of dt, the previous + * scan_for_updates() time. We also break out if we miss enough + * user input. + */ + if (dt > grind_spin_time) { + int i, ms, split = 30; + double shim; /* - * Try for some "quick" pointer input processing. - * - * About as fast as we can, we try to process user input - * calling rfbProcessEvents or rfbCheckFds. We do this - * for a time on order of the last scan_for_updates() time, - * dt, but if we stop getting user input we break out. - * We will also break out if we have processed max_eat - * inputs. - * - * Note that rfbCheckFds() does not send any framebuffer - * updates, so is more what we want here, although it is - * likely they have all be sent already. + * Break up our pause into 'split' steps. We get at + * most one input per step. */ - while (1) { + shim = 0.75 * dt / split; + + ms = (int) (1000 * shim); + + /* cutoff how long the pause can be */ + if (split * ms > 300) { + ms = 300 / split; + } + + spin = 0.0; + tm = 0.0; + dtime(&tm); + + g = got_pointer_input; + miss = 0; + for (i=0; i quick_spin_fac * dt) { - /* get out if spin time comparable to last scan time */ - break; - } if (got_pointer_input > g) { - g = got_pointer_input; - if (eaten++ < max_eat) { - continue; - } + XFlush(dpy); + miss = 0; } else { miss++; } - if (miss > 1) { /* 1 means out on 2nd miss */ + g = got_pointer_input; + if (miss > 2) { + break; + } + if (1000 * spin > ms * split) { break; } } + } +} +static void check_user_input3(double dt, double dtr, int tile_diffs) { - /* - * Probably grinding with a lot of fb I/O if dt is - * this large. (need to do this more elegantly) - * - * Current idea is to spin our wheels here *not* processing - * any fb I/O, but still processing the user input. - * This user input goes to the X display and changes it, - * but we don't poll it while we "rest" here for a time - * on order of dt, the previous scan_for_updates() time. - * We also break out if we miss enough user input. - */ - if (dt > grind_spin_time) { - int i, ms, split = 30; - double shim; - - /* - * Break up our pause into 'split' steps. - * We get at most one input per step. - */ - shim = 0.75 * dt / split; - - ms = (int) (1000 * shim); - - /* cutoff how long the pause can be */ - if (split * ms > 300) { - ms = 300 / split; - } + int allowed_misses, miss_tweak, i, g, g_in; + int last_was_miss, consecutive_misses; + double spin, spin_max, tm, to, dtm; + int rfb_wait_ms = 2; + static double dt_cut = 0.075; + int gcnt, ginput; + static int first = 1; - spin = 0.0; - tm = 0.0; - dtime(&tm); - g = got_pointer_input; - miss = 0; - for (i=0; i g) { - XFlush(dpy); - miss = 0; - } else { - miss++; - } - g = got_pointer_input; - if (miss > 2) { - break; - } - if (1000 * spin > ms * split) { - break; - } - } + if (first) { + char *p = getenv("SPIN"); + if (p) { + double junk; + sscanf(p, "%lf,%lf", &dt_cut, &junk); } + first = 0; } -} -static void check_user_input3(double dt, int tile_diffs) { + if (!got_pointer_input) { + return; + } - if (got_pointer_input) { - int spun_out, missed_out, allowed_misses, g, g_in; - double spin, spin_max, tm, to, dtm, rpe_last; - static int rfb_wait_ms = 2; - static double grind_spin_time = 0.30, dt_cut = 0.075; - static double quick_spin_fac = 0.65, spin_max_fac = 2.0; - static double rpe_wait = 0.15; - int grinding, gcnt, ms, split = 200; - static int first = 1; - if (first) { - char *p = getenv("SPIN"); - if (p) { - sscanf(p, "%lf,%lf,%lf", &grind_spin_time, &dt_cut, &quick_spin_fac); - } - first = 0; - } + if (dt < dt_cut) { + dt = dt_cut; /* this is to try to avoid early exit */ + } + spin_max = 0.5; + spin = 0.0; /* amount of time spinning */ + allowed_misses = 10; /* number of ptr inputs we can miss */ + miss_tweak = 8; + last_was_miss = 0; + consecutive_misses = 1; + gcnt = 0; + ginput = 0; - /* - * Try for some "quick" pointer input processing. - * - * About as fast as we can, we try to process user input - * calling rfbProcessEvents or rfbCheckFds. We do this - * for a time on order of the last scan_for_updates() time, - * dt, but if we stop getting user input we break out. - * - * Note that rfbCheckFds() does not send any framebuffer - * updates, so is more what we want here, although it is - * likely they have all be sent already. - * - * After our first spin_out or missed_out, we decide if we - * should continue, if we do so we say we are "grinding" - */ + tm = 0.0; /* timer variable */ + dtime(&tm); + to = tm; /* last time we did rfbPE() */ - if (dt < dt_cut) { - dt = dt_cut; /* this is to try to avoid early exit */ - } - /* max spin time in 1st pass, comparable to last dt */ - spin_max = quick_spin_fac * dt; + g = g_in = got_pointer_input; - grinding = 0; /* 1st pass is "not grinding" */ - spin = 0.0; /* amount of time spinning */ - spun_out = 0; /* whether we spun out of time */ - missed_out = 0; /* whether we received no ptr input */ - allowed_misses = 3; /* number of ptr inputs we can miss */ - gcnt = 0; + while (1) { + int got_input = 0; - tm = 0.0; /* timer variable */ - dtime(&tm); - rpe_last = to = tm; /* last time we did rfbPE() */ - g = g_in = got_pointer_input; + gcnt++; + if (button_mask) { + drag_in_progress = 1; + } - while (1) { - int got_input = 0; + rfbCFD(screen, rfb_wait_ms * 1000); - gcnt++; - if (grinding) { - if (gcnt >= split) { - break; - } - usleep(ms * 1000); - } + dtm = dtime(&tm); + spin += dtm; - if (button_mask) { - drag_in_progress = 1; + if (got_pointer_input == g) { + if (last_was_miss) { + consecutive_misses++; } - - if (show_multiple_cursors && tm > rpe_last + rpe_wait) { - rfbPE(screen, rfb_wait_ms * 1000); - rpe_last = tm; - } else { - rfbCFD(screen, rfb_wait_ms * 1000); + last_was_miss = 1; + } else { + ginput++; + if (ginput % miss_tweak == 0) { + allowed_misses++; } + consecutive_misses = 1; + last_was_miss = 0; + } - dtm = dtime(&tm); - spin += dtm; + if (spin > spin_max) { + /* get out if spin time over limit */ + break; - if (spin > spin_max) { - /* get out if spin time over limit */ - spun_out = 1; - } else if (got_pointer_input > g) { - /* received some input, flush to display. */ - got_input = 1; - g = got_pointer_input; - XFlush(dpy); - } else if (--allowed_misses <= 0) { - /* too many misses */ - missed_out = 1; + } else if (got_pointer_input > g) { + /* received some input, flush to display. */ + got_input = 1; + g = got_pointer_input; + X_LOCK; + XFlush(dpy); + X_UNLOCK; + } else if (--allowed_misses <= 0) { + /* too many misses */ + break; + } else if (consecutive_misses >=3) { + /* too many misses */ + break; + } else { + /* these are misses */ + int wms = 0; + if (gcnt == 1 && button_mask) { + /* + * missed our first input, wait + * for a defer time. (e.g. on + * slow link) hopefully client + * will batch them. + */ + wms = 50; + } else if (button_mask) { + wms = 10; } else { - /* these are misses */ - int wms = 0; - if (! grinding && gcnt == 1 && button_mask) { - /* - * missed our first input, wait - * for a defer time. (e.g. on - * slow link) hopefully client - * will batch them. - */ - wms = 1000 * (0.5 * (spin_max - spin)); - } else if (button_mask) { - wms = 10; - } else { - } - if (wms) { - usleep(wms * 1000); - } } - if (spun_out && ! grinding) { - /* set parameters for grinding mode. */ - - grinding = 1; - - if (spin > grind_spin_time || button_mask) { - spin_max = spin + - grind_spin_time * spin_max_fac; - } else { - spin_max = spin + dt * spin_max_fac; - } - ms = (int) (1000 * ((spin_max - spin)/split)); - if (ms < 1) { - ms = 1; - } - - /* reset for second pass */ - spun_out = 0; - missed_out = 0; - allowed_misses = 3; - g = got_pointer_input; - gcnt = 0; - } else if (spun_out && grinding) { - /* done in 2nd pass */ - break; - } else if (missed_out) { - /* done in either pass */ - break; + if (wms) { + usleep(wms * 1000); } } } + + if (ginput >= 2) { + /* try for a couple more quick ones */ + for (i=0; i<2; i++) { + rfbCFD(screen, rfb_wait_ms * 1000); + } + } + drag_in_progress = 0; } -/* quick-n-dirty copy of check_user_input3, merge later... */ +int fb_update_sent(int *count) { + static int last_count = 0; + int sent = 0, rc = 0; + rfbClientIteratorPtr i; + rfbClientPtr cl; -static void check_user_input4(double dt, int tile_diffs) { + i = rfbGetClientIterator(screen); + while( (cl = rfbClientIteratorNext(i)) ) { + sent += cl->framebufferUpdateMessagesSent; + } + rfbReleaseClientIterator(i); + if (sent != last_count) { + rc = 1; + } + if (count != NULL) { + *count = sent; + } + last_count = sent; + return rc; +} - int spun_out, missed_out, allowed_misses, g, g_in; - double spin, spin_max, tm, to, dtm, rpe_last; - static int rfb_wait_ms = 2; - static double grind_spin_time = 0.30, dt_cut = 0.075; - static double quick_spin_fac = 0.65, spin_max_fac = 2.0; - static double rpe_wait = 0.15; - int grinding, gcnt, ms, split = 200; +static void check_user_input4(double dt, double dtr, int tile_diffs) { + + int g, g_in, i, ginput, gcnt, tmp; + int last_was_miss, consecutive_misses; + int min_frame_size = 10; /* 10 tiles */ + double spin, tm, to, tc, dtm, rpe_last; + int rfb_wait_ms = 2; + static double dt_cut = 0.050; static int first = 1; - int Btile = tile_x * tile_y * bpp/8; - double Ttile; - double screen_rate = 5000000.; /* 5 MB/sec */ - double client_rate = 80 * 100000.; /* 20 KB/sec @ 80X compression */ - static double Tfac = 1.0; + int Btile = tile_x * tile_y * bpp/8; /* Bytes per tile */ + double Ttile, dt_use; + double screen_rate = 6000000.; /* 5 MB/sec */ + double vnccpu_rate = 80 * 100000.; /* 20 KB/sec @ 80X compression */ + double net_rate = 50000.; + static double Tfac_r = 1.0, Tfac_v = 1.0, Tfac_n = 1.0, Tdelay = 0.001; static double dt_min = -1.0, dt_max = -1.0; + double dt_min_fallback = 0.050; + static int ssec = 0, total_calls = 0; + static int push_frame = 0, update_count = 0; if (first) { char *p = getenv("SPIN"); if (p) { - sscanf(p, "%lf,%lf,%lf,%lf", &grind_spin_time, - &dt_cut, &quick_spin_fac, &Tfac); + sscanf(p, "%lf,%lf,%lf,%lf", &dt_cut, &Tfac_r, &Tfac_v, &Tfac_n); } first = 0; + ssec = time(0); } - if (dt_min < 0 || dt < dt_min) { - dt_min = dt; + total_calls++; + + if (dt_min < 0.0 || dt < dt_min) { + if (dt > 0.0) { + dt_min = dt; + } + } + if (dt_min < 0.0) { + /* sensible value for the very 1st call if dt = 0.0 */ + dt_min = dt_min_fallback; } - if (dt_max < 0 || dt > dt_max) { + if (dt_max < 0.0 || dt > dt_max) { dt_max = dt; } + if (total_calls > 30 && dt_min > 0.0) { + static int first = 1; + /* + * dt_min will soon be the quickest time to do + * one scan_for_updates with no tiles copied. + * use this (instead of copy_tiles) to estimate + * screen read rate. + */ + screen_rate = (main_bytes_per_line * ntiles_y) / dt_min; + if (first) { + rfbLog("measured screen read rate: %.2f Bytes/sec\n", + screen_rate); + } + first = 0; + } + + tm = 0.0; /* timer variable */ + dtime(&tm); + + if (dt < dt_cut) { + dt_use = dt_cut; + } else { + dt_use = dt; + } + + if (push_frame) { + int cnt, iter = 0; + double tp = 0.0, push_spin = 0.0; + dtime(&tp); + while (push_spin < dt_use * 0.5) { + fb_update_sent(&cnt); + if (cnt != update_count) { + break; + } + /* damn, they didn't push our frame! */ + iter++; + rfbPE(screen, rfb_wait_ms * 1000); + + push_spin += dtime(&tp); + } + if (iter) { + X_LOCK; + XFlush(dpy); + X_UNLOCK; + } + push_frame = 0; + update_count = 0; + } + /* * when we first enter we require some pointer input */ if (!got_pointer_input) { - drag_in_progress = 0; return; } - Ttile = Btile * (1.0/screen_rate + 1.0/client_rate); - Ttile = Tfac * Ttile; + vnccpu_rate = get_raw_rate(); - if (dt < dt_cut) { - dt = dt_cut; /* this is to try to avoid early exit */ + if ((tmp = get_read_rate()) != 0) { + screen_rate = (double) tmp; + } + if ((tmp = get_net_rate()) != 0) { + net_rate = (double) tmp; + } + net_rate = (vnccpu_rate/get_cmp_rate()) * net_rate; + + if ((tmp = get_net_latency()) != 0) { + Tdelay = 0.5 * ((double) tmp)/1000.; } - /* max spin time in 1st pass, comparable to last dt */ - spin_max = quick_spin_fac * dt; + Ttile = Btile * (Tfac_r/screen_rate + Tfac_v/vnccpu_rate + Tfac_n/net_rate); - grinding = 0; /* 1st pass is "not grinding" */ spin = 0.0; /* amount of time spinning */ - spun_out = 0; /* whether we spun out of time */ - missed_out = 0; /* whether we received no ptr input */ - allowed_misses = 3; /* number of ptr inputs we can miss */ + last_was_miss = 0; + consecutive_misses = 1; gcnt = 0; + ginput = 0; - tm = 0.0; /* timer variable */ - dtime(&tm); - rpe_last = to = tm; /* last time we did rfbPE() */ + rpe_last = to = tc = tm; /* last time we did rfbPE() */ g = g_in = got_pointer_input; + tile_diffs = 0; /* reset our knowlegde of tile_diffs to zero */ while (1) { int got_input = 0; gcnt++; - if (grinding) { - if (gcnt >= split) { - break; - } - usleep(ms * 1000); - } if (button_mask) { + /* this varible is used by our pointer handler */ drag_in_progress = 1; } - if (show_multiple_cursors && tm > rpe_last + rpe_wait) { - rfbPE(screen, rfb_wait_ms * 1000); - rpe_last = tm; - } else { - rfbCFD(screen, rfb_wait_ms * 1000); - } + /* turn libvncserver crank to process events: */ + rfbCFD(screen, rfb_wait_ms * 1000); dtm = dtime(&tm); spin += dtm; - if (spin > spin_max) { - /* get out if spin time over limit */ - spun_out = 1; + if ( (gcnt == 1 && got_pointer_input > g) || tm-tc > 2*dt_min) { + tile_diffs = scan_for_updates(1); + tc = tm; + } - } else if (tile_diffs > 200 && spin > Ttile * tile_diffs) { - /* XXX not finished. */ + if (got_pointer_input == g) { + if (last_was_miss) { + consecutive_misses++; + } + last_was_miss = 1; + } else { + ginput++; + consecutive_misses = 1; + last_was_miss = 0; + } + + if (tile_diffs > min_frame_size && spin > Ttile * tile_diffs + Tdelay) { /* we think we can push the frame */ + push_frame = 1; + fb_update_sent(&update_count); break; } else if (got_pointer_input > g) { - /* received some input, flush to display. */ + /* received some input, flush it to display. */ got_input = 1; g = got_pointer_input; + X_LOCK; XFlush(dpy); + X_UNLOCK; - } else if (--allowed_misses <= 0) { - /* too many misses */ - missed_out = 1; + } else if (consecutive_misses >= 2) { + /* too many misses in a row */ + break; } else { - /* these are misses */ - int wms = 0; - if (! grinding && gcnt == 1 && button_mask) { + /* these are pointer input misses */ + int wms; + if (gcnt == 1 && button_mask) { /* * missed our first input, wait for * a defer time. (e.g. on slow link) - * hopefully client will batch them. + * hopefully client will batch many + * of them for the next read. */ - wms = 1000 * (0.5 * (spin_max - spin)); + wms = 50; } else if (button_mask) { wms = 10; + } else { + wms = 0; } if (wms) { usleep(wms * 1000); - } - } - if (spun_out && ! grinding) { - /* set parameters for grinding mode. */ - - grinding = 1; - - if (spin > grind_spin_time || button_mask) { - spin_max = spin + - grind_spin_time * spin_max_fac; - } else { - spin_max = spin + dt * spin_max_fac; - } - ms = (int) (1000 * ((spin_max - spin)/split)); - if (ms < 1) { - ms = 1; - } - - /* reset for second pass */ - spun_out = 0; - missed_out = 0; - allowed_misses = 3; - g = got_pointer_input; - gcnt = 0; - - } else if (spun_out && grinding) { - /* done in 2nd pass */ - break; - } else if (missed_out) { - /* done in either pass */ - break; + } + } + } + if (ginput >= 2) { + /* try for a couple more quick ones */ + for (i=0; i<2; i++) { + rfbCFD(screen, rfb_wait_ms * 1000); } } drag_in_progress = 0; } -static int check_user_input(double dt, int tile_diffs, int *cnt) { +static int check_user_input(double dt, double dtr, int tile_diffs, int *cnt) { if (pointer_mode == 1) { if ((got_user_input || ui_skip < 0) && *cnt % ui_skip != 0) { /* every ui_skip-th drops thru to scan */ *cnt++; + X_LOCK; XFlush(dpy); + X_UNLOCK; return 1; /* short circuit watch_loop */ } else { return 0; @@ -13424,19 +13966,24 @@ static int check_user_input(double dt, int tile_diffs, int *cnt) { } if (pointer_mode >= 2 && pointer_mode <= 4) { if (got_keyboard_input) { + /* + * for these modes, short circuit watch_loop on + * *keyboard* input. + */ if (*cnt % ui_skip != 0) { *cnt++; - return 1; /* short circuit watch_loop */ + return 1; } } - /* otherwise continue with pointer input */ + /* otherwise continue below with pointer input method */ } + if (pointer_mode == 2) { check_user_input2(dt); } else if (pointer_mode == 3) { - check_user_input3(dt, tile_diffs); + check_user_input3(dt, dtr, tile_diffs); } else if (pointer_mode == 4) { - check_user_input4(dt, tile_diffs); + check_user_input4(dt, dtr, tile_diffs); } return 0; } @@ -13448,7 +13995,7 @@ static int check_user_input(double dt, int tile_diffs, int *cnt) { double dtime(double *t_old) { /* * usage: call with 0.0 to initialize, subsequent calls give - * the time differences. + * the time difference since last call. */ double t_now, dt; struct timeval now; @@ -13464,17 +14011,273 @@ double dtime(double *t_old) { return(dt); } +void measure_display_hook(rfbClientPtr cl) { + ClientData *cd = (ClientData *) cl->clientData; + cd->timer = 0.0; + dtime(&cd->timer); +} + +void measure_send_rates_init(void) { + int i, bs, rbs; + rfbClientIteratorPtr iter; + rfbClientPtr cl; + + screen->displayHook = measure_display_hook; + + iter = rfbGetClientIterator(screen); + while( (cl = rfbClientIteratorNext(iter)) ) { + ClientData *cd = (ClientData *) cl->clientData; + bs = 0; + for (i=0; ibytesSent[i]; + } + rbs = cl->rawBytesEquivalent; + + cd->set_cmp_bytes = bs; + cd->set_raw_bytes = rbs; + cd->timer = -1.0; + } + rfbReleaseClientIterator(iter); +} + +int get_rate(int which) { + rfbClientIteratorPtr iter; + rfbClientPtr cl; + int i, samples = RATE_SAMPLES; + double dslowest = -1.0, dsum; + + iter = rfbGetClientIterator(screen); + while( (cl = rfbClientIteratorNext(iter)) ) { + ClientData *cd = (ClientData *) cl->clientData; + + dsum = 0.0; + for (i=0; icmp_samp[i]; + } else { + dsum += cd->raw_samp[i]; + } + } + dsum = dsum / samples; + if (dsum > dslowest) { + dslowest = dsum; + } + + } + rfbReleaseClientIterator(iter); + + if (dslowest < 0.0) { + if (which == 0) { + dslowest = 5000.0; + } else { + dslowest = 50000.0; + } + } + return (int) dslowest; +} + +int get_cmp_rate(void) { + return get_rate(0); +} + +int get_raw_rate(void) { + return get_rate(1); +} + +void initialize_speeds(void) { + char *s, *p; + int i; + + speeds_read_rate = 0; + speeds_net_rate = 0; + speeds_net_latency = 0; + if (! speeds_str || *speeds_str == '\0') { + return; + } + + if (!strcmp(speeds_str, "modem")) { + s = strdup("6,4,200"); + } else if (!strcmp(speeds_str, "dsl")) { + s = strdup("6,100,50"); + } else if (!strcmp(speeds_str, "modem")) { + s = strdup("6,5000,1"); + } else { + s = strdup(speeds_str); + } + + p = strtok(s, ","); + i = 0; + while (p) { + double val; + if (*p != '\0') { + val = atof(p); + if (i==0) { + speeds_read_rate = (int) 1000000 * val; + } else if (i==1) { + speeds_net_rate = (int) 1000 * val; + } else if (i==2) { + speeds_net_latency = (int) val; + } + } + i++; + p = strtok(NULL, ","); + } + free(s); +} + +int get_read_rate(void) { + if (speeds_read_rate) { + return speeds_read_rate; + } + return 0; +} + +int get_net_rate(void) { + if (speeds_net_rate) { + return speeds_net_rate; + } + return 0; +} + +int get_net_latency(void) { + if (speeds_net_latency) { + return speeds_net_latency; + } + return 0; +} + +void measure_send_rates(int init) { + int i, j, nclient = 0; + int min_width = 200; + double dt, cmp_rate, raw_rate; + rfbClientPtr id[100]; + double dts[100], dts_sorted[100], dtmp; + int sorted[100], did[100], best; + rfbClientIteratorPtr iter; + rfbClientPtr cl; + + if (! measure_speeds) { + return; + } + if (init) { + measure_send_rates_init(); + return; + } + + iter = rfbGetClientIterator(screen); + while( (cl = rfbClientIteratorNext(iter)) ) { + double tmp2; + ClientData *cd = (ClientData *) cl->clientData; + tmp2 = 0.0; + dtime(&tmp2); +if (init) { + continue; +} + if (cd->timer <= 0.0) { + continue; + } + dt = dtime(&cd->timer); + cd->timer = dt; + if (nclient < 100) { + id[nclient] = cl; + dts[nclient] = dt; + nclient++; + } + } + rfbReleaseClientIterator(iter); +if (init) { + return; +} + + for (i=0; i dtmp) { + best = j; + dtmp = dts[j]; + } + } + did[best] = 1; + sorted[i] = best; + dts_sorted[i] = dts[best]; + } + + + iter = rfbGetClientIterator(screen); + while( (cl = rfbClientIteratorNext(iter)) ) { + int db, dbr, cbs, rbs; + ClientData *cd = (ClientData *) cl->clientData; + + dt = cd->timer; + if (dt <= 0.0) { + continue; + } + if (nclient > 1) { + for (i=0; ibytesSent[i]; + } + rbs = cl->rawBytesEquivalent; + + db = cbs - cd->set_cmp_bytes; + dbr = rbs - cd->set_raw_bytes; + cmp_rate = db/dt; + raw_rate = dbr/dt; + if (dbr > min_width * min_width * bpp/8) { + cd->sample++; + if (cd->sample >= RATE_SAMPLES) { + cd->sample = 0; + } + i = cd->sample; + cd->cmp_samp[i] = cmp_rate; + cd->raw_samp[i] = raw_rate; + } + } + rfbReleaseClientIterator(iter); +} + /* * utility wrapper to call rfbProcessEvents * checks that we are not in threaded mode. */ void rfbPE(rfbScreenInfoPtr scr, long usec) { + if (! scr) { + return; + } if (! use_threads) { rfbProcessEvents(scr, usec); } } void rfbCFD(rfbScreenInfoPtr scr, long usec) { + if (! scr) { + return; + } if (! use_threads) { rfbCheckFds(scr, usec); } @@ -13485,7 +14288,7 @@ void rfbCFD(rfbScreenInfoPtr scr, long usec) { */ static void watch_loop(void) { int cnt = 0, tile_diffs = 0; - double dt = 0.0; + double dt = 0.0, dtr = 0.0; if (use_threads) { rfbRunEventLoop(screen, -1, TRUE); @@ -13498,12 +14301,18 @@ static void watch_loop(void) { got_keyboard_input = 0; if (! use_threads) { + double tm = 0.0; + dtime(&tm); rfbPE(screen, -1); + dtr = dtime(&tm); + fb_update_sent(NULL); + if (! cursor_shape_updates) { /* undo any cursor shape requests */ disable_cursor_shape_updates(screen); } - if (check_user_input(dt, tile_diffs, &cnt)) { + if (screen && screen->clientHead && + check_user_input(dt, dtr, tile_diffs, &cnt)) { /* true means loop back for more input */ continue; } @@ -13522,7 +14331,8 @@ static void watch_loop(void) { check_connect_inputs(); check_padded_fb(); - if (! screen->clientHead) { /* waiting for a client */ + if (! screen || ! screen->clientHead) { + /* waiting for a client */ usleep(200 * 1000); continue; } @@ -13542,7 +14352,8 @@ static void watch_loop(void) { */ check_bell_event(); } - if (! show_dragging && button_mask) { + + if (button_mask && (!show_dragging || pointer_mode == 0)) { /* * if any button is pressed do not update rfb * screen, but do flush the X11 display. @@ -13556,7 +14367,15 @@ static void watch_loop(void) { dtime(&tm); rfbUndrawCursor(screen); - tile_diffs = scan_for_updates(); + if (use_snapfb) { + int t, tries = 5; + copy_snap(); + for (t =0; t < tries; t++) { + tile_diffs = scan_for_updates(0); + } + } else { + tile_diffs = scan_for_updates(0); + } dt = dtime(&tm); check_x11_pointer(); } @@ -13618,7 +14437,7 @@ static void print_help(void) { " support MIT-SHM. Equivalent to setting the DISPLAY\n" " environment variable to \"disp\".\n" "-auth file Set the X authority file to be \"file\", equivalent to\n" -" setting the XAUTHORITY environment varirable to \"file\"\n" +" setting the XAUTHORITY environment variable to \"file\"\n" " before startup. See Xsecurity(7), xauth(1) man pages.\n" "\n" "-id windowid Show the window corresponding to \"windowid\" not\n" @@ -13864,7 +14683,8 @@ static void print_help(void) { " -remote id:windowid, rescaling, etc.\n" "\n" "-o logfile Write stderr messages to file \"logfile\" instead of\n" -" to the terminal. Same as \"-logfile file\".\n" +" to the terminal. Same as \"-logfile file\". To append\n" +" to the file use \"-oa file\" or \"-logappend file\".\n" "-rc filename Use \"filename\" instead of $HOME/.x11vncrc for rc file.\n" "-norc Do not process any .x11vncrc file for options.\n" "-h, -help Print this help text.\n" @@ -14045,6 +14865,14 @@ static void print_help(void) { " black background). Specify this option to remove the\n" " alpha factor. (useful for light colored semi-transparent\n" " cursors).\n" +"-alphablend In XFIXES mode send cursor alpha channel data to\n" +" libvncserver. The blending effect will only be\n" +" visible in -nocursorshape mode or for clients with\n" +" cursorshapeupdates turned off. (However there is a\n" +" hack for 32bpp with depth 24, it uses the extra 8 bits\n" +" to store cursor transparency for use with a hacked\n" +" vncviewer that applies the transparency locally.\n" +" See the FAQ for more info).\n" "\n" "-nocursorshape Do not use the TightVNC CursorShapeUpdates extension\n" " even if clients support it. See -cursor above.\n" @@ -14081,38 +14909,85 @@ static void print_help(void) { " initial state of the modifier is ignored and not reset)\n" " To include button events use \"Button1\", ... etc.\n" "\n" -"-nodragging Do not update the display during mouse dragging\n" -" events (mouse motion with a button held down).\n" -" Greatly improves response on slow setups, but you lose\n" -" all visual feedback for drags, text selection, and some\n" -" menu traversals. It overrides any -pointer_mode setting\n" -" (think of it as pointer_mode 0)\n" -"-pointer_mode n Various pointer update schemes. The problem is pointer\n" -" motion can cause rapid changes on the screen, e.g. a\n" -" window drag. Neither x11vnc's screen polling nor the\n" +"-nodragging Do not update the display during mouse dragging events\n" +" (mouse button held down). Greatly improves response on\n" +" slow setups, but you lose all visual feedback for drags,\n" +" text selection, and some menu traversals. It overrides\n" +" any -pointer_mode setting\n" +"-pointer_mode n Various pointer motion update schemes. \"-pm\" is\n" +" an alias. The problem is pointer motion can cause\n" +" rapid changes on the screen: consider the rapid changes\n" +" when you drag a large window around. Neither x11vnc's\n" +" screen polling and vnc compression routines nor the\n" " bandwidth to the vncviewers can keep up these rapid\n" -" screen changes: everything bogs down when dragging\n" -" or scrolling. Note that most video h/w is optimized\n" -" for writing, not reading (a 50X rate difference is\n" -" possible) and x11vnc is reading all the time. So a\n" -" scheme has to be used to \"eat\" much of that pointer\n" -" input before re-polling the screen. n can be 1 to %d.\n" +" screen changes: everything will bog down when dragging\n" +" or scrolling. So a scheme has to be used to \"eat\"\n" +" much of that pointer input before re-polling the screen\n" +" and sending out framebuffer updates. The mode number\n" +" \"n\" can be 0 to %d and selects one of the schemes\n" +" desribed below.\n" +"\n" +" n=0: does the same as -nodragging. (all screen polling\n" +" is suspended if a mouse button is pressed.)\n" +"\n" +" n=1: was the original scheme used to about Jan 2004:\n" +" it basically just skips -input_skip keyboard or pointer\n" +" events before repolling the screen.\n" +"\n" +" n=2 is an improved scheme: by watching the current rate\n" +" of input events it tries to detect if it should try to\n" +" \"eat\" additional pointer events before continuing.\n" +"\n" +" n=3 is basically a dynamic -nodragging mode: it detects\n" +" when the mouse motion has paused and then refreshes\n" +" the display.\n" +"\n" +" n=4: attempts to measures network rates and latency,\n" +" the video card read rate, and how many tiles have been\n" +" changed on the screen. From this, it aggressively tries\n" +" to push screen \"frames\" when it decides it has enough\n" +" resources to do so. NOT FINISHED.\n" +"\n" +" The default n is %d. Note that modes 2, 3, 4 will skip\n" +" -input_skip keyboard events (but it will not count\n" +" pointer events). Also note that these modes are not\n" +" available in -threads mode which has its own pointer\n" +" event handling mechanism.\n" +"\n" +" To try out the different pointer modes to see\n" +" which one gives the best response for your usage,\n" +" it is convenient to use the remote control function,\n" +" e.g. \"x11vnc -R pointer_mode:4\" or the tcl/tk gui\n" +" (Tuning -> pointer_mode -> n).\n" "\n" -" n=1 was the original scheme used to about Jan 2004: it\n" -" basically just skips -input_skip pointer events before\n" -" repolling the screen. n=2 is an improved scheme:\n" -" by watching the current rate it tries to detect if\n" -" it should try to \"eat\" more pointer events. n=3 is\n" -" basically a dynamic -nodragging mode: it detects if the\n" -" mouse drag motion has paused and refreshes the display.\n" -" n=4 is TBD, it will try measure screen read and client\n" -" write rates and try to insert \"frames\" between the\n" -" on/off states of mode 3. The default n is %d.\n" "-input_skip n For the pointer handling when non-threaded: try to\n" " read n user input events before scanning display. n < 0\n" " means to act as though there is always user input.\n" " Default: %d\n" "\n" +"-speeds rd,bw,lat x11vnc tries to estimate some speed parameters that\n" +" are used to optimize scheduling (e.g. -pointer_mode\n" +" 4) and other things. Use the -speeds option to set\n" +" these manually. The triple \"rd,bw,lat\" corresponds\n" +" to video h/w read rate in MB/sec, network bandwidth to\n" +" clients in KB/sec, and network latency to clients in\n" +" milliseconds, respectively. If a value is left blank,\n" +" e.g. \"-speeds ,100,15\", then the internal scheme is\n" +" used to estimate the empty value(s).\n" +"\n" +" Typical PC video cards have read rates of 5-10 MB/sec.\n" +" If the framebuffer is in main memory instead of video\n" +" h/w (e.g. SunRay, shadowfb, Xvfb), the read rate may\n" +" be much faster. \"x11perf -getimage500\" can be used\n" +" to get a lower bound (remember to factor in the bytes\n" +" per pixel). It is up to you to estimate the network\n" +" bandwith to clients. For the latency the ping(1)\n" +" command can be used.\n" +"\n" +" For convenience there are some aliases provided,\n" +" e.g. \"-speeds modem\". The aliases are: \"modem\" for\n" +" 6,4,200; \"dsl\" for 6,100,50; and \"lan\" for 6,5000,1\n" +"\n" "-debug_pointer Print debugging output for every pointer event.\n" "-debug_keyboard Print debugging output for every keyboard event.\n" " Same as -dp and -dk, respectively. Use multiple\n" @@ -14145,6 +15020,19 @@ static void print_help(void) { " by checking the tile near the boundary. Default: %d\n" "-fuzz n Tolerance in pixels to mark a tiles edges as changed.\n" " Default: %d\n" +"-snapfb Instead of polling the X display framebuffer (fb) for\n" +" changes, periodically copy all of X display fb into main\n" +" memory and examine that copy for changes. Under some\n" +" circumstances this will improve interactive response,\n" +" or at least make things look smoother, but in others\n" +" (many) it will make the response worse. If the video\n" +" h/w fb is such that reading small tiles is very slow\n" +" this mode could help. To keep the \"framerate\" up\n" +" the screen size x bpp cannot be too large. Note that\n" +" this mode is very wasteful of memory I/O resources\n" +" (it makes full screen copies even if nothing changes).\n" +" It may be of use in video capture-like applications,\n" +" or where window tearing is a problem.\n" "\n" "-gui [gui-opts] Start up a simple tcl/tk gui based on the the remote\n" " control options -remote/-query described below.\n" @@ -14331,6 +15219,8 @@ static void print_help(void) { " alphafrac:f set -alphafrac to f.\n" " alpharemove enable -alpharemove mode.\n" " noalpharemove disable -alpharemove mode.\n" +" alphablend enable -alphablend mode.\n" +" noalphablend disable -alphablend mode.\n" " cursorshape disable -nocursorshape mode.\n" " nocursorshape enable -nocursorshape mode.\n" " cursorpos disable -nocursorpos mode.\n" @@ -14340,8 +15230,9 @@ static void print_help(void) { " buttonmap:str set -buttonmap \"str\", empty to disable\n" " dragging disable -nodragging mode.\n" " nodragging enable -nodragging mode.\n" -" pointer_mode n set -pointer_mode to n.\n" -" input_skip n set -input_skip to n.\n" +" pointer_mode:n set -pointer_mode to n. same as \"pm\"\n" +" input_skip:n set -input_skip to n.\n" +" speeds:str set -speeds to str.\n" " debug_pointer enable -debug_pointer, same as \"dp\"\n" " nodebug_pointer disable -debug_pointer, same as \"nodp\"\n" " debug_keyboard enable -debug_keyboard, same as \"dk\"\n" @@ -14356,6 +15247,8 @@ static void print_help(void) { " gaps:n set -gaps to n.\n" " grow:n set -grow to n.\n" " fuzz:n set -fuzz to n.\n" +" snapfb enable -snapfb mode.\n" +" nosnapfb disable -snapfb mode.\n" " progressive:n set libvncserver -progressive slice\n" " height parameter to n.\n" " desktop:str set -desktop name to str for new clients.\n" @@ -14415,29 +15308,30 @@ static void print_help(void) { " variables correspond to the presence of X extensions):\n" "\n" " ans= stop quit exit shutdown ping blacken zero\n" -" refresh reset close disconnect id sid flashcmap\n" -" noflashcmap truecolor notruecolor overlay nooverlay\n" -" overlay_cursor overlay_yescursor nooverlay_nocursor\n" -" nooverlay_cursor nooverlay_yescursor overlay_nocursor\n" -" visual scale viewonly noviewonly shared noshared\n" -" forever noforever once deny lock nodeny unlock\n" -" connect allowonce allow localhost nolocalhost accept\n" -" gone shm noshm flipbyteorder noflipbyteorder onetile\n" -" noonetile blackout xinerama noxinerama xrandr noxrandr\n" -" xrandr_mode padgeom quiet q noquiet modtweak nomodtweak\n" -" xkb noxkb skip_keycodes add_keysyms noadd_keysyms\n" -" clear_mods noclear_mods clear_keys noclear_keys\n" -" remap repeat norepeat fb nofb bell nobell sel\n" -" nosel primary noprimary cursorshape nocursorshape\n" +" refresh reset close disconnect id sid waitmapped\n" +" nowaitmapped flashcmap noflashcmap truecolor notruecolor\n" +" overlay nooverlay overlay_cursor overlay_yescursor\n" +" nooverlay_nocursor nooverlay_cursor nooverlay_yescursor\n" +" overlay_nocursor visual scale viewonly noviewonly\n" +" shared noshared forever noforever once deny lock nodeny\n" +" unlock connect allowonce allow localhost nolocalhost\n" +" accept gone shm noshm flipbyteorder noflipbyteorder\n" +" onetile noonetile blackout xinerama noxinerama xrandr\n" +" noxrandr xrandr_mode padgeom quiet q noquiet modtweak\n" +" nomodtweak xkb noxkb skip_keycodes add_keysyms\n" +" noadd_keysyms clear_mods noclear_mods clear_keys\n" +" noclear_keys remap repeat norepeat fb nofb bell nobell\n" +" sel nosel primary noprimary cursorshape nocursorshape\n" " cursorpos nocursorpos cursor show_cursor noshow_cursor\n" -" nocursor xfixes noxfixes alphacut alphafrac alpharemove\n" -" noalpharemove xwarp xwarppointer noxwarp noxwarppointer\n" -" buttonmap dragging nodragging pointer_mode input_skip\n" -" debug_pointer dp nodebug_pointer nodp debug_keyboard\n" -" dk nodebug_keyboard nodk deferupdate defer wait\n" -" rfbwait nap nonap sb screen_blank fs gaps grow fuzz\n" -" progressive rfbport http nohttp httpport httpdir\n" -" enablehttpproxy noenablehttpproxy alwaysshared\n" +" nocursor xfixes noxfixes alphacut alphafrac\n" +" alpharemove noalpharemove alphablend noalphablend\n" +" xwarp xwarppointer noxwarp noxwarppointer buttonmap\n" +" dragging nodragging pointer_mode pm input_skip speeds\n" +" debug_pointer dp nodebug_pointer nodp debug_keyboard dk\n" +" nodebug_keyboard nodk deferupdate defer wait rfbwait\n" +" nap nonap sb screen_blank fs gaps grow fuzz snapfb\n" +" nosnapfb progressive rfbport http nohttp httpport\n" +" httpdir enablehttpproxy noenablehttpproxy alwaysshared\n" " noalwaysshared nevershared noalwaysshared dontdisconnect\n" " nodontdisconnect desktop noremote\n" "\n" @@ -14533,6 +15427,59 @@ static void print_help(void) { exit(1); } +void set_vnc_desktop_name(void) { + int sz = 256; + sprintf(vnc_desktop_name, "unknown"); + if (screen->port) { + char *host = this_host(); + int lport = screen->port; + if (host != NULL) { + /* note that vncviewer special cases 5900-5999 */ + if (inetd) { + ; /* should not occur (port) */ + } else if (quiet) { + if (lport >= 5900) { + snprintf(vnc_desktop_name, sz, "%s:%d", + host, lport - 5900); + fprintf(stderr, "The VNC desktop is " + "%s\n", vnc_desktop_name); + } else { + snprintf(vnc_desktop_name, sz, "%s:%d", + host, lport); + fprintf(stderr, "The VNC desktop is " + "%s\n", vnc_desktop_name); + } + } else if (lport >= 5900) { + snprintf(vnc_desktop_name, sz, "%s:%d", + host, lport - 5900); + rfbLog("\n"); + rfbLog("The VNC desktop is %s\n", + vnc_desktop_name); + if (lport >= 6000) { + rfbLog("possible aliases: %s:%d, " + "%s::%d\n", host, lport, + host, lport); + } + } else { + snprintf(vnc_desktop_name, sz, "%s:%d", + host, lport); + rfbLog("\n"); + rfbLog("The VNC desktop is %s\n", + vnc_desktop_name); + rfbLog("possible alias: %s::%d\n", + host, lport); + } + } + fflush(stderr); + if (inetd) { + ; /* should not occur (port) */ + } else { + fprintf(stdout, "PORT=%d\n", screen->port); + } + fflush(stdout); + } +} + /* * utility to get the current host name */ @@ -14582,14 +15529,13 @@ static char *choose_title(char *display) { * check blacklist for OSs with tight shm limits. */ static int limit_shm(void) { - struct utsname ut; int limit = 0; - if (uname(&ut) == -1) { + if (UT.sysname == NULL) { return 0; } - if (!strcmp(ut.sysname, "SunOS")) { - char *r = ut.release; + if (!strcmp(UT.sysname, "SunOS")) { + char *r = UT.release; if (*r == '5' && *(r+1) == '.') { if (strchr("2345678", *(r+2)) != NULL) { limit = 1; @@ -14598,7 +15544,7 @@ static int limit_shm(void) { } if (limit && ! quiet) { fprintf(stderr, "reducing shm usage on %s %s (adding " - "-onetile)\n", ut.sysname, ut.release); + "-onetile)\n", UT.sysname, UT.release); } return limit; } @@ -14670,12 +15616,12 @@ static void check_rcfile(int argc, char **argv) { perror("fstat"); exit(1); } - sz = sbuf.st_size+1; + sz = sbuf.st_size+1; /* allocate whole file size */ if (sz < 1024) { sz = 1024; } - buf = (char *) malloc(sz); + buf = (char *) malloc(sz); while (fgets(line, 4096, rc) != NULL) { char *q, *p = line; @@ -14791,7 +15737,7 @@ int main(int argc, char* argv[]) { int remote_sync = 0; char *remote_cmd = NULL; char *query_cmd = NULL; - char *gui_string = NULL; + char *gui_str = NULL; int pw_loc = -1; int vpw_loc = -1; int dt = 0, bg = 0; @@ -14873,6 +15819,8 @@ int main(int argc, char* argv[]) { argv[i]); exit(1); } + } else if (!strcmp(arg, "-waitmapped")) { + subwin_wait_mapped = 1; } else if (!strcmp(arg, "-flashcmap")) { flash_cmap = 1; } else if (!strcmp(arg, "-notruecolor")) { @@ -14948,7 +15896,7 @@ int main(int argc, char* argv[]) { single_copytile = 1; } else if (!strcmp(arg, "-blackout")) { CHECK_ARGC - blackout_string = strdup(argv[++i]); + blackout_str = strdup(argv[++i]); } else if (!strcmp(arg, "-xinerama")) { xinerama = 1; } else if (!strcmp(arg, "-xrandr")) { @@ -14966,6 +15914,11 @@ int main(int argc, char* argv[]) { pad_geometry = strdup(argv[++i]); } else if (!strcmp(arg, "-o") || !strcmp(arg, "-logfile")) { CHECK_ARGC + logfile_append = 0; + logfile = strdup(argv[++i]); + } else if (!strcmp(arg, "-oa") || !strcmp(arg, "-logappend")) { + CHECK_ARGC + logfile_append = 1; logfile = strdup(argv[++i]); } else if (!strcmp(arg, "-rc")) { i++; /* done above */ @@ -15045,6 +15998,8 @@ int main(int argc, char* argv[]) { alpha_frac = atof(argv[++i]); } else if (!strcmp(arg, "-alpharemove")) { alpha_remove = 1; + } else if (!strcmp(arg, "-alphablend")) { + alpha_blend = 1; } else if (!strcmp(arg, "-nocursorshape")) { cursor_shape_updates = 0; } else if (!strcmp(arg, "-cursorpos")) { @@ -15058,7 +16013,8 @@ int main(int argc, char* argv[]) { pointer_remap = strdup(argv[++i]); } else if (!strcmp(arg, "-nodragging")) { show_dragging = 0; - } else if (!strcmp(arg, "-pointer_mode")) { + } else if (!strcmp(arg, "-pointer_mode") + || !strcmp(arg, "-pm")) { char *p, *s; CHECK_ARGC s = argv[++i]; @@ -15077,6 +16033,9 @@ int main(int argc, char* argv[]) { CHECK_ARGC ui_skip = atoi(argv[++i]); if (! ui_skip) ui_skip = 1; + } else if (!strcmp(arg, "-speeds")) { + CHECK_ARGC + speeds_str = strdup(argv[++i]); } else if (!strcmp(arg, "-debug_pointer") || !strcmp(arg, "-dp")) { debug_pointer++; @@ -15122,12 +16081,14 @@ int main(int argc, char* argv[]) { } else if (!strcmp(arg, "-fuzz")) { CHECK_ARGC tile_fuzz = atoi(argv[++i]); + } else if (!strcmp(arg, "-snapfb")) { + use_snapfb = 1; } else if (!strcmp(arg, "-gui")) { launch_gui = 1; if (i < argc-1) { char *s = argv[i+1]; if (*s != '-') { - gui_string = strdup(s); + gui_str = strdup(s); i++; } } @@ -15191,11 +16152,16 @@ int main(int argc, char* argv[]) { } if (launch_gui) { - do_gui(gui_string); + do_gui(gui_str); } if (logfile) { int n; - if ((n = open(logfile, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) { + if (logfile_append) { + n = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0666); + } else { + n = open(logfile, O_WRONLY|O_CREAT|O_TRUNC, 0666); + } + if (n < 0) { fprintf(stderr, "error opening logfile: %s\n", logfile); perror("open"); exit(1); @@ -15324,6 +16290,7 @@ int main(int argc, char* argv[]) { if (waitms < 0) { waitms = 0; } + if (alpha_threshold < 0) { alpha_threshold = 0; } @@ -15336,6 +16303,10 @@ int main(int argc, char* argv[]) { if (alpha_frac > 1.0) { alpha_frac = 1.0; } + if (alpha_blend) { + alpha_remove = 0; + } + if (inetd) { shared = 0; connect_once = 1; @@ -15404,13 +16375,13 @@ int main(int argc, char* argv[]) { fprintf(stderr, " authfile: %s\n", auth_file ? auth_file : "null"); fprintf(stderr, " subwin: 0x%lx\n", subwin); - fprintf(stderr, " rootshift: %d\n", rootshift); + fprintf(stderr, " -sid mode: %d\n", rootshift); fprintf(stderr, " flashcmap: %d\n", flash_cmap); fprintf(stderr, " force_idx: %d\n", force_indexed_color); - fprintf(stderr, " overlay: %d\n", overlay); - fprintf(stderr, " ovl_cursor: %d\n", overlay_cursor); fprintf(stderr, " visual: %s\n", visual_str ? visual_str : "null"); + fprintf(stderr, " overlay: %d\n", overlay); + fprintf(stderr, " ovl_cursor: %d\n", overlay_cursor); fprintf(stderr, " scaling: %d %.5f\n", scaling, scale_fac); fprintf(stderr, " viewonly: %d\n", view_only); fprintf(stderr, " shared: %d\n", shared); @@ -15432,14 +16403,17 @@ int main(int argc, char* argv[]) { fprintf(stderr, " using_shm: %d\n", using_shm); fprintf(stderr, " flipbytes: %d\n", flip_byte_order); fprintf(stderr, " onetile: %d\n", single_copytile); - fprintf(stderr, " blackout: %s\n", blackout_string - ? blackout_string : "null"); + fprintf(stderr, " blackout: %s\n", blackout_str + ? blackout_str : "null"); fprintf(stderr, " xinerama: %d\n", xinerama); fprintf(stderr, " xrandr: %d\n", xrandr); fprintf(stderr, " xrandrmode: %s\n", xrandr_mode ? xrandr_mode : "null"); + fprintf(stderr, " padgeom: %s\n", pad_geometry + ? pad_geometry : "null"); fprintf(stderr, " logfile: %s\n", logfile ? logfile : "null"); + fprintf(stderr, " logappend: %d\n", logfile_append); fprintf(stderr, " rc_file: %s\n", rc_rcfile ? rc_rcfile : "null"); fprintf(stderr, " norc: %d\n", rc_norc); @@ -15460,11 +16434,15 @@ int main(int argc, char* argv[]) { fprintf(stderr, " watchsel: %d\n", watch_selection); fprintf(stderr, " watchprim: %d\n", watch_primary); fprintf(stderr, " cursor: %d\n", show_cursor); - fprintf(stderr, " root_curs: %d\n", show_multiple_cursors); + fprintf(stderr, " multicurs: %d\n", show_multiple_cursors); fprintf(stderr, " curs_mode: %s\n", multiple_cursors_mode ? multiple_cursors_mode : "null"); fprintf(stderr, " xfixes: %d\n", use_xfixes); - fprintf(stderr, " cursorshp: %d\n", cursor_shape_updates); + fprintf(stderr, " alphacut: %d\n", alpha_threshold); + fprintf(stderr, " alphafrac: %.2f\n", alpha_frac); + fprintf(stderr, " alpharemove:%d\n", alpha_remove); + fprintf(stderr, " alphablend: %d\n", alpha_blend); + fprintf(stderr, " cursorshape:%d\n", cursor_shape_updates); fprintf(stderr, " cursorpos: %d\n", cursor_pos_updates); fprintf(stderr, " xwarpptr: %d\n", use_xwarppointer); fprintf(stderr, " buttonmap: %s\n", pointer_remap @@ -15472,6 +16450,8 @@ int main(int argc, char* argv[]) { fprintf(stderr, " dragging: %d\n", show_dragging); fprintf(stderr, " ptr_mode: %d\n", pointer_mode); fprintf(stderr, " inputskip: %d\n", ui_skip); + fprintf(stderr, " speeds: %s\n", speeds_str + ? speeds_str : "null"); fprintf(stderr, " debug_ptr: %d\n", debug_pointer); fprintf(stderr, " debug_key: %d\n", debug_keyboard); fprintf(stderr, " defer: %d\n", defer_update); @@ -15485,8 +16465,13 @@ int main(int argc, char* argv[]) { 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, " deny_all: %d\n", deny_all); + fprintf(stderr, " snapfb: %d\n", use_snapfb); + fprintf(stderr, " gui: %d\n", launch_gui); + fprintf(stderr, " gui_mode: %s\n", gui_str + ? gui_str : "null"); fprintf(stderr, " noremote: %d\n", !accept_remote_cmds); + fprintf(stderr, " safemode: %d\n", safe_remote_only); + fprintf(stderr, " deny_all: %d\n", deny_all); fprintf(stderr, "\n"); rfbLog("x11vnc version: %s\n", lastmod); } else { @@ -15689,6 +16674,9 @@ int main(int argc, char* argv[]) { */ XTestGrabControl_wr(dpy, True); + /* set OS struct UT */ + uname(&UT); + /* check for OS with small shm limits */ if (using_shm && ! single_copytile) { if (limit_shm()) { @@ -15778,6 +16766,8 @@ int main(int argc, char* argv[]) { initialize_signals(); + initialize_speeds(); + initialize_keyboard_and_pointer(); if (! inetd) { @@ -15789,53 +16779,7 @@ int main(int argc, char* argv[]) { if (! quiet) { rfbLog("screen setup finished.\n"); } - sprintf(vnc_desktop_name, "unknown"); - if (screen->port) { - char *host = this_host(); - int lport = screen->port; - if (host != NULL) { - /* note that vncviewer special cases 5900-5999 */ - if (inetd) { - ; /* should not occur (port) */ - } else if (quiet) { - if (lport >= 5900) { - sprintf(vnc_desktop_name, "%s:%d", - host, lport - 5900); - fprintf(stderr, "The VNC desktop is " - "%s\n", vnc_desktop_name); - } else { - sprintf(vnc_desktop_name, "%s:%d", - host, lport); - fprintf(stderr, "The VNC desktop is " - "%s\n", vnc_desktop_name); - } - } else if (lport >= 5900) { - sprintf(vnc_desktop_name, "%s:%d", - host, lport - 5900); - rfbLog("\n"); - rfbLog("The VNC desktop is %s\n", - vnc_desktop_name); - if (lport >= 6000) { - rfbLog("possible aliases: %s:%d, " - "%s::%d\n", host, lport, host, lport); - } - } else { - sprintf(vnc_desktop_name, "%s:%d", host, lport); - rfbLog("\n"); - rfbLog("The VNC desktop is %s\n", - vnc_desktop_name); - rfbLog("possible alias: %s::%d\n", - host, lport); - } - } - fflush(stderr); - if (inetd) { - ; /* should not occur (port) */ - } else { - fprintf(stdout, "PORT=%d\n", screen->port); - } - fflush(stdout); - } + set_vnc_desktop_name(); #if LIBVNCSERVER_HAVE_FORK && LIBVNCSERVER_HAVE_SETSID if (bg) {