-/* xscreensaver, Copyright (c) 2001-2004 by Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2001-2006 by Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
#define GETIMAGE_FILE_PROGRAM "xscreensaver-getimage-file"
#define GETIMAGE_SCREEN_PROGRAM "xscreensaver-getimage-desktop"
+extern const char *blurb (void);
+
const char *
blurb (void)
{
return 0;
}
+#ifndef USE_EXTERNAL_SCREEN_GRABBER
static int
ignore_badmatch_ehandler (Display *dpy, XErrorEvent *error)
{
else
return x_ehandler (dpy, error);
}
+#endif /* ! USE_EXTERNAL_SCREEN_GRABBER */
/* Returns True if the given Drawable is a Window; False if it's a Pixmap.
Atom type;
int format;
unsigned long nitems, bytesafter;
- char *version;
+ unsigned char *version;
if (window != RootWindowOfScreen (screen))
return False;
XInternAtom (dpy, "_SCREENSAVER_VERSION", False),
0, 1, False, XA_STRING,
&type, &format, &nitems, &bytesafter,
- (unsigned char **) &version)
+ &version)
== Success
&& type != None)
return False;
*scaled_to_y_ret = desty;
if (verbose_p)
- fprintf (stderr, "%s: displaying %dx%d image at %d,%d.\n",
- progname, src_w, src_h, destx, desty);
+ fprintf (stderr, "%s: displaying %dx%d image at %d,%d in %dx%d.\n",
+ progname, src_w, src_h, destx, desty, dest_w, dest_h);
}
If out of memory, returns False, and the XImage will have been
destroyed and freed.
*/
+#if !defined(USE_EXTERNAL_SCREEN_GRABBER) || defined(HAVE_JPEGLIB)
static Bool
scale_ximage (Screen *screen, Visual *visual,
XImage *ximage, int new_width, int new_height)
return True;
}
+#endif /* !USE_EXTERNAL_SCREEN_GRABBER || HAVE_JPEGLIB */
#ifdef HAVE_GDK_PIXBUF
*/
static Bool
read_file_gdk (Screen *screen, Window window, Drawable drawable,
- const char *filename, Bool verbose_p)
+ const char *filename, Bool verbose_p,
+ XRectangle *geom_ret)
{
GdkPixbuf *pb;
Display *dpy = DisplayOfScreen (screen);
XSetWindowBackgroundPixmap (dpy, window, drawable);
XClearWindow (dpy, window);
}
+
+ if (geom_ret)
+ {
+ geom_ret->x = destx;
+ geom_ret->y = desty;
+ geom_ret->width = w;
+ geom_ret->height = h;
+ }
}
XSync (dpy, False);
*/
static Bool
read_file_jpeglib (Screen *screen, Window window, Drawable drawable,
- const char *filename, Bool verbose_p)
+ const char *filename, Bool verbose_p,
+ XRectangle *geom_ret)
{
Display *dpy = DisplayOfScreen (screen);
XImage *ximage;
XFreeGC (dpy, gc);
}
+ if (geom_ret)
+ {
+ geom_ret->x = destx;
+ geom_ret->y = desty;
+ geom_ret->width = ximage->width;
+ geom_ret->height = ximage->height;
+ }
+
free (ximage->data);
ximage->data = 0;
XDestroyImage (ximage);
*/
static Bool
display_file (Screen *screen, Window window, Drawable drawable,
- const char *filename, Bool verbose_p)
+ const char *filename, Bool verbose_p,
+ XRectangle *geom_ret)
{
if (verbose_p)
fprintf (stderr, "%s: loading \"%s\"\n", progname, filename);
# if defined(HAVE_GDK_PIXBUF)
- if (read_file_gdk (screen, window, drawable, filename, verbose_p))
+ if (read_file_gdk (screen, window, drawable, filename, verbose_p, geom_ret))
return True;
# elif defined(HAVE_JPEGLIB)
- if (read_file_jpeglib (screen, window, drawable, filename, verbose_p))
+ if (read_file_jpeglib (screen, window, drawable, filename, verbose_p,
+ geom_ret))
return True;
# else /* !(HAVE_GDK_PIXBUF || HAVE_JPEGLIB) */
/* shouldn't get here if we have no image-loading methods available. */
/* Invokes a sub-process and returns its output (presumably, a file to
- load.) Free the string when done. video_p controls which program
+ load.) Free the string when done. 'grab_type' controls which program
to run.
*/
static char *
close (out); /* don't need this one */
*buf = 0;
- fgets (buf, sizeof(buf)-1, f);
+ if (! fgets (buf, sizeof(buf)-1, f))
+ *buf = 0;
fclose (f);
/* Wait for the child to die. */
*/
static Bool
display_video (Screen *screen, Window window, Drawable drawable,
- Bool verbose_p)
+ Bool verbose_p, XRectangle *geom_ret)
{
char *filename = get_video_filename (screen, verbose_p);
Bool status;
return False;
}
- status = display_file (screen, window, drawable, filename, verbose_p);
+ status = display_file (screen, window, drawable, filename, verbose_p,
+ geom_ret);
if (unlink (filename))
{
*/
static Bool
display_desktop (Screen *screen, Window window, Drawable drawable,
- Bool verbose_p)
+ Bool verbose_p, XRectangle *geom_ret)
{
# ifdef USE_EXTERNAL_SCREEN_GRABBER
return False;
}
- status = display_file (screen, window, drawable, filename, verbose_p);
+ status = display_file (screen, window, drawable, filename, verbose_p,
+ geom_ret);
if (unlink (filename))
{
XFreeGC (dpy, gc);
}
+ if (geom_ret)
+ {
+ geom_ret->x = destx;
+ geom_ret->y = desty;
+ geom_ret->width = w2;
+ geom_ret->height = h2;
+ }
+
XSync (dpy, False);
return True;
}
+/* Whether the given Drawable is unreasonably small.
+ */
+static Bool
+drawable_miniscule_p (Display *dpy, Drawable drawable)
+{
+ Window root;
+ int xx, yy;
+ unsigned int bw, d, w = 0, h = 0;
+ XGetGeometry (dpy, drawable, &root, &xx, &yy, &w, &h, &bw, &d);
+ return (w < 32 || h < 32);
+}
+
+
/* Grabs an image (from a file, video, or the desktop) and renders it on
the Drawable. If `file' is specified, always use that file. Otherwise,
select randomly, based on the other arguments.
{
Display *dpy = DisplayOfScreen (screen);
grab_type which = GRAB_BARS;
- int count = 0;
struct stat st;
const char *file_prop = 0;
+ XRectangle geom = { 0, 0, 0, 0 };
if (! drawable_window_p (dpy, window))
{
image_p = False;
}
+ /* If the target drawable is really small, no good can come of that.
+ Always do colorbars in that case.
+ */
+ if (drawable_miniscule_p (dpy, drawable))
+ {
+ desk_p = False;
+ video_p = False;
+ image_p = False;
+ }
# ifndef _VROOT_H_
# error Error! This file definitely needs vroot.h!
}
# endif /* !USE_EXTERNAL_SCREEN_GRABBER */
- count = 0;
- if (desk_p) count++;
- if (video_p) count++;
- if (image_p) count++;
-
- if (count == 0)
+ if (! (desk_p || video_p || image_p))
which = GRAB_BARS;
else
{
int i = 0;
- while (1) /* loop until we get one that's permitted */
- {
- which = (random() % 3);
- if (which == GRAB_DESK && desk_p) break;
- if (which == GRAB_VIDEO && video_p) break;
- if (which == GRAB_FILE && image_p) break;
- if (++i > 200) abort();
- }
+ int n;
+ /* Loop until we get one that's permitted.
+ If files or video are permitted, do them more often
+ than desktop.
+
+ D+V+I: 10% + 45% + 45%.
+ V+I: 50% + 50%
+ D+V: 18% + 82%
+ D+I: 18% + 82%
+ */
+ AGAIN:
+ n = (random() % 100);
+ if (++i > 300) abort();
+ else if (desk_p && n < 10) which = GRAB_DESK; /* 10% */
+ else if (video_p && n < 55) which = GRAB_VIDEO; /* 45% */
+ else if (image_p) which = GRAB_FILE; /* 45% */
+ else goto AGAIN;
}
break;
case GRAB_DESK:
- if (! display_desktop (screen, window, drawable, verbose_p))
+ if (! display_desktop (screen, window, drawable, verbose_p, &geom))
goto COLORBARS;
file_prop = "desktop";
break;
case GRAB_FILE:
- if (! display_file (screen, window, drawable, file, verbose_p))
+ if (! display_file (screen, window, drawable, file, verbose_p, &geom))
goto COLORBARS;
file_prop = file;
break;
case GRAB_VIDEO:
- if (! display_video (screen, window, drawable, verbose_p))
+ if (! display_video (screen, window, drawable, verbose_p, &geom))
goto COLORBARS;
file_prop = "video";
break;
(unsigned char *) file_prop, strlen(file_prop));
else
XDeleteProperty (dpy, window, a);
+
+ a = XInternAtom (dpy, XA_XSCREENSAVER_IMAGE_GEOMETRY, False);
+ if (geom.width > 0)
+ {
+ char gstr[30];
+ sprintf (gstr, "%dx%d+%d+%d", geom.width, geom.height, geom.x, geom.y);
+ XChangeProperty (dpy, window, a, XA_STRING, 8, PropModeReplace,
+ (unsigned char *) gstr, strlen (gstr));
+ }
+ else
+ XDeleteProperty (dpy, window, a);
}
XSync (dpy, False);
memset (&P, 0, sizeof(P));
P.db = db;
- load_init_file (&P);
+ load_init_file (dpy, &P);
progname = argv[0] = oprogname;