--- a/Imakefile
+++ b/Imakefile
@@ -1,4 +1,4 @@
-  LOCAL_LIBRARIES = $(XLIB)
+  LOCAL_LIBRARIES = $(XLIB) -lm
              SRCS = floatbg.c
              OBJS = floatbg.o
 SYSLAST_LIBRARIES = -lm
--- a/floatbg.c
+++ b/floatbg.c
@@ -3,9 +3,24 @@
  *	author: Jan Rekers
  *	purpose: This program slowly changes the color of the root window of X.
  */
+/* 16bpp and 32bpp support added by Dave Holland <dave@zenda.demon.co.uk>
+ * Code taken from xsetroot by Mark Lillibridge
+ * Copyright (c) 1987,  X Consortium
+ */
+/* Further modifications by Varis (risto.varanka@helsinki.fi) 22.10.1999
+ */
 
 #include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <math.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
 
 #define MaxColor 	0xffff
 #define MaxTime  	0x7fff
@@ -14,11 +29,16 @@
 #define default_s_mid	.375
 #define default_s_var	.125
 #define default_v_val	.87
+#define default_l_time	10.00
+#define atom_name	"floatbg_running"
 
 char *program_name;
+int gnome=0; /* call out to gconftool to affect Gnome background */
+int xfce=0; /* call out to xfconf-query to affect Xfce background */
 Display *dpy;
 int screen;
 Window root;
+Atom running_flag;
 
 struct hsv { float h,s,v; };
 struct rgb { float r,g,b; };
@@ -28,27 +48,49 @@ float sf_in_hf = default_sf_in_hf;
 float s_mid = default_s_mid;
 float s_var = default_s_var;
 float v_val = default_v_val;
+float l_time = default_l_time;
 
 unsigned long GetMutableColor();
 void SetColor();
-long time(), random();
-double atof();
+/* We no longer need these, since we now include stdlib.h and time.h.  */
+/* long time(), random(); */
+/* double atof(); */
+
+/* from xsetroot */
+unsigned long NameToPixel();
+int save_colors=0;
+
+char str[100];
+int using8bpp=0;
 
-usage()
+void usage(void)
 {
     fprintf(stderr, "usage: %s [options]\n", program_name);
     fprintf(stderr, "  where options are:\n");
     fprintf(stderr, "  -display <display>   or   -d <display>\n");
     fprintf(stderr, "  -help\n");
+    fprintf(stderr, "  -gnome\n");
+    fprintf(stderr, "  -xfce\n");
     fprintf(stderr, "  -value <float>   (default %1.2f)\n", default_v_val);
     fprintf(stderr, "  -satmid <float>  (default %1.3f)\n", default_s_mid);
     fprintf(stderr, "  -satvar <float>  (default %1.3f)\n", default_s_var);
     fprintf(stderr, "  -fase <float>    (default %1.2f)\n", default_sf_in_hf);
+    fprintf(stderr, "  -time <float>    (default %1.2f)\n", default_l_time);
     fprintf(stderr, "  value, (satmid-satvar) and (satmid+satvar) must be between 0 and 1\n");
     exit(1);
 }
 
-main(argc, argv) 
+void clear_flag_exit(int signum) {
+    int i;
+
+    //fprintf(stderr, "received signal %d: clearing flag and exiting\n", signum);
+    i = XDeleteProperty(dpy, root, running_flag);
+    //fprintf(stderr, "i=%d\n");
+    XFlush(dpy);
+    exit(0);
+}
+
+int main(argc, argv) 
     int argc;
     char **argv;
 {
@@ -59,7 +101,8 @@ main(argc, argv)
     struct hsv hsv;
     struct rgb rgb;
     extern char *optarg;
-
+    struct timeval looptime, tmptime; 
+ 
     program_name=argv[0];
     for (i = 1; i < argc; i++) {
 	if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) {
@@ -70,6 +113,14 @@ main(argc, argv)
 	if (!strcmp("-help", argv[i])) {
 	    usage();
 	}
+	if (!strcmp("-gnome", argv[i])) {
+	    gnome=1;
+            continue;
+	}
+	if (!strcmp("-xfce", argv[i])) {
+	    xfce=1;
+            continue;
+	}
 	if (!strcmp("-value", argv[i])) {
 	    if (++i>=argc) usage();
 	    v_val = atof(argv[i]);
@@ -90,6 +141,11 @@ main(argc, argv)
 	    sf_in_hf = atof(argv[i]);
 	    continue;
 	}
+	if (!strcmp("-time", argv[i])) {
+	    if (++i>=argc) usage();
+	    l_time = atof(argv[i]);
+	    continue;
+	}
 	usage();
     } 
 
@@ -105,19 +161,83 @@ main(argc, argv)
     screen = DefaultScreen(dpy);
     root = RootWindow(dpy, screen);
 
-    srandom( (int)time(0L) );
+    /* create the atom if it's not already there */
+    running_flag = XInternAtom(dpy, atom_name, False);
+
+    Atom actual_type_return;
+    int actual_format_return;
+    unsigned long nitems_return, bytes_after_return;
+    unsigned char *prop_return;
+    /* look for signs of life elsewhere */
+    i = XGetWindowProperty(dpy, root, running_flag, 0, 1, False, AnyPropertyType, 
+            &actual_type_return, &actual_format_return, &nitems_return,
+            &bytes_after_return, &prop_return);
+    //fprintf(stderr, "i=%d, nitems_return=%d\n", i, nitems_return);
+    if (nitems_return != 0) {
+        fprintf(stderr, "%s: another copy may be running; exiting\n", program_name);
+        exit(0);
+    }
+    i = XChangeProperty(dpy, root, running_flag, XA_ATOM, 32, PropModeReplace,
+            "flbg", 1);
+    //fprintf(stderr, "i=%d\n");
+    i = XGetWindowProperty(dpy, root, running_flag, 0, 1, False, AnyPropertyType, 
+            &actual_type_return, &actual_format_return, &nitems_return,
+            &bytes_after_return, &prop_return);
+    //fprintf(stderr, "i=%d, nitems_return=%d\n", i, nitems_return);
+
+    /* if we can't create the signal handler, there's not much we can */
+    /* do, so throw away the return code here */
+    signal(SIGHUP, (void *)clear_flag_exit);
+    signal(SIGTERM, (void *)clear_flag_exit);
+    signal(SIGINT, (void *)clear_flag_exit);
+    signal(SIGKILL, (void *)clear_flag_exit);
+
+    srandom( (int)time(NULL) );
     ticks = (int)random() % MaxTime;
 
+    /* this will trigger a change to using 8bpp if appropriate */
     cmapentry = GetMutableColor();
-    XSetWindowBackground(dpy, root, cmapentry);
-    XClearWindow(dpy, root);
+
+    /* for 16/32bpp this'll happen in the main loop */
+    if(using8bpp) {
+        XSetWindowBackground(dpy, root, cmapentry);
+        XClearWindow(dpy, root);
+    }
+
+    /* Set time values for select - ie. how long to wait between loops */
+    looptime.tv_sec = 0;
+    looptime.tv_usec = 0;
+    if (l_time >= 1) {
+      looptime.tv_sec = l_time;
+      l_time = l_time - looptime.tv_sec;
+    }
+    if ((l_time < 1) && (l_time > 0)) {
+      looptime.tv_usec = 1000000*l_time;
+    }
+
+    if(gnome) {
+        system("gconftool --type string --set /desktop/gnome/background/color_shading_type \"solid\"");
+        system("gconftool --unset /desktop/gnome/background/picture_filename");
+    }
+    if(xfce) {
+        system("xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitor0/image-show -n -s false");
+        system("xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitor0/color-style -n -s 0");
+    }
+
+    /* The Linux kernel time share clock ticks at 100Hz on i386, */
+    /* so this loop will not run more than 100 times a second. */
+    /* On Alpha this is reported to be 1000Hz. */
+
     while ( 1 ) {
-	ticks2hsv(ticks, &hsv);
+       	ticks2hsv(ticks, &hsv);
 	hsv2rgb(&hsv, &rgb);
-	SetColor(cmapentry, &rgb);
+	SetColor(cmapentry, &rgb, dpy, root, screen);
 	XFlush(dpy);
 	ticks = ticks++ % MaxTime;
-	sleep(10);
+	/* select seems to alter the timeval struct, so we need */
+	/* an extra variable */
+	tmptime = looptime;
+	select(0, NULL, NULL, NULL, &tmptime);
     }
 }
 
@@ -125,32 +245,61 @@ unsigned long GetMutableColor ()
 {
     XColor color;
     if (XAllocColorCells (dpy, DefaultColormap(dpy,screen),
-			  0, 0, 0, &color.pixel, 1) == NULL) {
-	fprintf(stderr, "%s:  unable to allocate colorcells\n", program_name);
-	exit(1); }
+			  0, 0, 0, &color.pixel, 1) == 0) {
+	/* this is not an 8bpp display */
+	return (unsigned long) 0;
+	}
+    using8bpp=1;
     return(color.pixel);
 }
 
-void SetColor (pixel, rgb)
+void SetColor (pixel, rgb, dpy, root, screen)
     unsigned long pixel;
     struct rgb *rgb;
+    Display *dpy;
+    int screen;
+    Window root;
 {
     XColor color;
-    int red = (int) MaxColor * rgb->r;
-    int green = (int) MaxColor * rgb->g;
-    int blue = (int) MaxColor * rgb->b;
-
-    color.red = red; color.green = green; color.blue = blue;
-    color.pixel = pixel;
-    color.flags = DoRed|DoGreen|DoBlue;
-    XStoreColor(dpy, DefaultColormap(dpy,screen), &color);
+    unsigned int red = (int) MaxColor * rgb->r;
+    unsigned int green = (int) MaxColor * rgb->g;
+    unsigned int blue = (int) MaxColor * rgb->b;
+
+    if(gnome) {
+        /* I'm sorry. */
+	char cmd[120];
+	sprintf(cmd,"gconftool --type string --set /desktop/gnome/background/primary_color \"#%04x%04x%04x\"",
+	    red, green, blue);
+        /* printf("%s\n",cmd); */
+	system(cmd);
+    } else if(xfce) {
+        /* I'm sorry for this, too. */
+        char cmd[200];
+        sprintf(cmd,"xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitor0/color1 -n -t uint16 -s %d -t uint16 -s %d -t uint16 -s %d -t uint16 -s 65535", red, green, blue);
+        system(cmd);
+    } else {
+        if(using8bpp) {
+        /* this will not work in 16/32bpp */
+            color.red = red; color.green = green; color.blue = blue;
+            color.pixel = pixel;
+            color.flags = DoRed|DoGreen|DoBlue;
+            XStoreColor(dpy, DefaultColormap(dpy,screen), &color);
+        } else {
+        /* this method _does_ work in 16/32bpp; also 8bpp although
+         * the above method is apparently less resource-hungry */
+        sprintf(str,"#%.4x%.4x%.4x",red,green,blue);
+            XSetWindowBackground(dpy, root,
+    			 NameToPixel(str, BlackPixel(dpy,screen)));
+            XClearWindow(dpy,root);
+        }
+    }
 }
 
 void ticks2hsv (ticks, hsv)
     int ticks;
     struct hsv *hsv;
 {
-    float s_fase, sin();
+    float s_fase /*, sin() */ ;
 
     hsv->h = ticks % 360;
     s_fase = sf_in_hf * (pi / 180) * ticks;
@@ -185,3 +334,31 @@ void hsv2rgb (hsv, rgb)
 	}
     }
 }
+
+#define Dynamic 1
+
+unsigned long NameToPixel(name, pixel)
+    char *name;
+    unsigned long pixel;
+{
+    XColor ecolor;
+
+    if (!name || !*name)
+	return pixel;
+    if (!XParseColor(dpy,DefaultColormap(dpy,screen),name,&ecolor)) {
+	fprintf(stderr,"%s:  unknown color \"%s\"\n",program_name,name);
+	exit(1);
+	/*NOTREACHED*/
+    }
+    if (!XAllocColor(dpy, DefaultColormap(dpy, screen),&ecolor)) {
+	fprintf(stderr, "%s:  unable to allocate color for \"%s\"\n",
+		program_name, name);
+	exit(1);
+	/*NOTREACHED*/
+    }
+    if ((ecolor.pixel != BlackPixel(dpy, screen)) &&
+	(ecolor.pixel != WhitePixel(dpy, screen)) &&
+	(DefaultVisual(dpy, screen)->class & Dynamic))
+	save_colors = 1;
+    return(ecolor.pixel);
+}
--- a/floatbg.man
+++ b/floatbg.man
@@ -5,17 +5,20 @@ floatbg \- slowly modify the color of th
 \fBfloatbg\fP
 [-display \fIdisplay\fP]
 [-help]
+[-gnome]
+[-xfce]
 [-value \fIfloat\fP] 
 [-satmid \fIfloat\fP] 
 [-satvar \fIfloat\fP] 
 [-fase \fIfloat\fP] 
+[-time \fIfloat\fP]
 .SH DESCRIPTION
 Floatbg is an X11 program that modifies the color of the root window
-in such a manner that you won't to see the color change,
+in such a manner that you won't see the color change,
 but after a while you'll notice that it did change, however.
 .PP
-Floatbg starts with a random color and changes it deterministicly by moving
-through a hsv-model of colors.
+Floatbg starts with a random color and changes it deterministically by moving
+through an hsv-model of colors.
 In the hsv-model, colors are described by three parameters:
 Hue stands for the tint of a color
 (0 degrees is red, 60 = yellow, 120 = green, 180 = aquamarine, etc),
@@ -26,12 +29,19 @@ and value stands for the intensity of th
 .PP
 Every 10 seconds the hue (tint) is increased by one degree
 and the saturation (brightness) is changed by a sinus over the hue.
-The shape of this sinus can be addapted with
+(The frequency of this change can be adjusted with the -time parameter.)
+The shape of this sinus can be adapted with
 the options -satmid, -satvar and -fase.
 The value (blackness) is fixed and can be set with the option -value.
 The default values are: 
 \fIfloatbg -value .87 -satmid .375 -satvar .125 -fase .25\fP,
 and are such that all pastel tints are visited.
+.PP
+Extremely simplistic Gnome and Xfce support can be enabled with the
+\fI-gnome\fP
+and
+\fI-xfce\fP
+flags.
 .SH BUGS
 Floatbg doesn't use any window, button or menu,
 and it can only be stopped by killing it.
