Fixing the XAnalogTV Screensaver
A few days ago, I discovered the awesome XAnalogTV screensaver included with XScreenSaver. I was very impressed with the visuals, which include a very accurate simulation of a conventional “tube” television implementing the analog NTSC TV standard. There was just one problem – I couldn’t get XAnalogTV to fill my screen:

In the source code, the virtual "display" is forced to be within 15% of a standard 4:3 display. Any screen which is outside of this 15% range is just clipped, as shown in this image.
In the above screenshot, pay attention to the edges of the screen. For some reason, the way the scaling/clipping was implemented caused the clipped portions on the screen’s edges to simply not be drawn (as they should be drawn or cleared to pure black). This causes the screensaver to look quite odd, especially when there’s perfectly drawn digital graphics being rendered behind the wonderful analog “snow”. I found this only happens when the aspect ratio of the XAnalogTV window was very different than 4:3. Thus, in my quest for beautifully simulated analog graphics, I set out to fix this error.
I set out to download the source code from Jamie Zawinski’s website, but at the time I wrote the post, the file he uploaded was corrupted (it has since been fixed). My next stop to find the source code lead me to the Ubuntu Package Repository, where I was able to download the source code (xscreensaver_5.15.orig.tar.gz). If you have a different Linux distribution, you should be able to get the source code from the distribution repository’s website.
After extracting the source code, I went into the source directory, and called ./configure. After it figured out I was missing a bunch of packages, I got all of the build dependencies via apt, and re-ran ./configure successfully:
sudo apt-get build-dep xscreensaver ./configure
Now, it was time to start analyzing the source code. I figured the best area to start looking at would be the code that gets executed when the screen is resized from xanalogtv.c:
static void xanalogtv_reshape (Display *dpy, Window window, void *closure, unsigned int w, unsigned int h) { struct state *st = (struct state *) closure; analogtv_reconfigure(st->tv); }
So, XAnalogTV uses helper functions embedded in another file, analogtv.c. Looking at the analogtv_reconfigure() function, all it does is pass an object to the analogtv_configure() function. There, I found the following code near the beginning of the function (comments removed):
float percent = 0.15; /* jwz: 20% caused severe top/bottom clipping in Pong on 1680x1050 iMac screen. */ float min_ratio = 4.0 / 3.0 * (1 - percent); float max_ratio = 4.0 / 3.0 * (1 + percent); float ratio; float height_snap=0.025; hlim = it->xgwa.height; wlim = it->xgwa.width; ratio = wlim / (float) hlim; if (wlim < 266 || hlim < 200) { wlim = 266; hlim = 200; # ifdef DEBUG fprintf (stderr, "size: minimal: %dx%d in %dx%d (%.3f < %.3f < %.3f)\n", wlim, hlim, it->xgwa.width, it->xgwa.height, min_ratio, ratio, max_ratio); # endif } else if (ratio > min_ratio && ratio < max_ratio) { # ifdef DEBUG fprintf (stderr, "size: close enough: %dx%d (%.3f < %.3f < %.3f)\n", wlim, hlim, min_ratio, ratio, max_ratio); # endif } else if (ratio > max_ratio) { wlim = hlim*max_ratio; # ifdef DEBUG fprintf (stderr, "size: center H: %dx%d in %dx%d (%.3f < %.3f < %.3f)\n", wlim, hlim, it->xgwa.width, it->xgwa.height, min_ratio, ratio, max_ratio); # endif } else /* ratio < min_ratio */ { hlim = wlim/min_ratio; # ifdef DEBUG fprintf (stderr, "size: center V: %dx%d in %dx%d (%.3f < %.3f < %.3f)\n", wlim, hlim, it->xgwa.width, it->xgwa.height, min_ratio, ratio, max_ratio); # endif }
From the above code, you can see that the author set the screensaver to stop scaling to fit when the aspect ratio exceeded ± 15% of a typical 4:3 NTSC TV. This is fine, although something must be happening in the draw function to prevent the clipped parts of the screen from actually being drawn/updated.
So as a temporary fix, I modified XAnalogTV to just stretch to fit your screen by commenting out lines 328 and 338 in analogtv.c, which are listed below (respectively):
wlim = hlim*max_ratio; /* Comment these two lines out (or remove them entirely) */ hlim = wlim/min_ratio; /* to prevent XAnalogTV from reshaping the display. */
After that, I recompiled xscreensaver using make. Instead of calling make-install, however, I simply copied my newly compiled version of the XAnalogTV binary overtop of the older one (which was found in /usr/lib/xscreensaver/xanalogtv):
cp /usr/lib/xscreensaver/xanalogtv /usr/lib/xscreensaver/xanalogtv.bak sudo cp ./hacks/xanalogtv /usr/lib/xscreensaver/
After restarting the xscreensaver daemon, the screensaver now works as expected:



Finally – sombody found the solution! Much thanks. However, there was no space, it’s “wlim = hlim*max_ratio;”
Thank you for pointing that out, Dan. I’ve updated article accordingly.
thats great, those visible borders are really annoying! i cant work out this make thing though :(
Hi Lexi;
Sounds like you might not have some of the required build dependencies. Check the output from make, and see if it says anything regarding missing libraries or header files (indicating you might need the -dev versions of some packages).
Thanks,
Brandon
I enjoyed reading the write-up, hope I can discover a lot more articles like this one. Thanks for posting.