-/* xscreensaver, Copyright (c) 2001-2004 by Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2001-2013 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
#ifdef __APPLE__
- /* On MacOSX / XDarwin, the usual X11 mechanism of getting a screen shot
- doesn't work, and we need to use an external program. */
+ /* On MacOS under X11, the usual X11 mechanism of getting a screen shot
+ doesn't work, and we need to use an external program. This is only
+ used when running under X11 on MacOS. If it's a Cocoa build, this
+ path is not taken, and OSX/osxgrabscreen.m is used instead.
+ */
# define USE_EXTERNAL_SCREEN_GRABBER
#endif
#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.
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
&root, &x, &y, &win_width, &win_height, &bw, &win_depth);
}
- gdk_pixbuf_xlib_init (dpy, screen_number (screen));
+ gdk_pixbuf_xlib_init_with_depth (dpy, screen_number (screen), win_depth);
# ifdef HAVE_GTK2
+# if !GLIB_CHECK_VERSION(2, 36 ,0)
g_type_init();
+# endif
# else /* !HAVE_GTK2 */
xlib_rgb_init (dpy, screen);
# endif /* !HAVE_GTK2 */
int srcx, srcy, destx, desty, w2, h2;
Bool bg_p = False;
+# ifdef HAVE_GDK_PIXBUF_APPLY_EMBEDDED_ORIENTATION
+ {
+ int ow = w, oh = h;
+ GdkPixbuf *opb = pb;
+ pb = gdk_pixbuf_apply_embedded_orientation (opb);
+ g_object_unref (opb);
+ w = gdk_pixbuf_get_width (pb);
+ h = gdk_pixbuf_get_height (pb);
+ if (verbose_p && (w != ow || h != oh))
+ fprintf (stderr, "%s: rotated %dx%d to %dx%d\n",
+ progname, ow, oh, w, h);
+ }
+# endif
+
compute_image_scaling (w, h, win_width, win_height, verbose_p,
&srcx, &srcy, &destx, &desty, &w2, &h2);
if (w != w2 || h != h2)
GDK_INTERP_BILINEAR);
if (pb2)
{
- gdk_pixbuf_unref (pb);
+ g_object_unref (pb);
pb = pb2;
w = w2;
h = h2;
/* Allocates a colormap that makes a PseudoColor or DirectColor
visual behave like a TrueColor visual of the same depth.
+
+ #### Duplicated in utils/grabscreen.c
*/
static void
allocate_cubic_colormap (Screen *screen, Visual *visual, Colormap cmap,
/* Find the pixel index that is closest to the given color
(using linear distance in RGB space -- which is far from the best way.)
+
+ #### Duplicated in utils/grabscreen.c
*/
static unsigned long
find_closest_pixel (XColor *colors, int ncolors,
displayable with the given X colormap. The farther from a perfect
color cube the contents of the colormap are, the lossier the
transformation will be. No dithering is done.
+
+ #### Duplicated in utils/grabscreen.c
*/
static void
remap_image (Screen *screen, Colormap cmap, XImage *image, Bool verbose_p)
/* Invokes a sub-process and returns its output (presumably, a file to
load.) Free the string when done. 'grab_type' controls which program
- to run.
+ to run. Returned pathname may be relative to 'directory', or absolute.
*/
static char *
get_filename_1 (Screen *screen, const char *directory, grab_type type,
pid_t forked;
int fds [2];
int in, out;
- char buf[1024];
+ char buf[10240];
char *av[20];
int ac = 0;
int wait_status = 0;
FILE *f = fdopen (in, "r");
int L;
+ char *ret = 0;
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. */
if (!*buf)
return 0;
+
+ ret = strdup (buf);
+
+ if (*ret != '/')
+ {
+ /* Program returned path relative to directory. Prepend dir
+ to buf so that we can properly stat it. */
+ strcpy (buf, directory);
+ if (directory[strlen(directory)-1] != '/')
+ strcat (buf, "/");
+ strcat (buf, ret);
+ }
+
if (stat(buf, &st))
{
fprintf (stderr, "%s: file does not exist: \"%s\"\n",
progname, buf);
+ free (ret);
return 0;
}
else
- return strdup (buf);
+ return ret;
}
}
}
+/* 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;
+ char *absfile = 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!
We cannot grab desktop images that way if:
- the window is a non-top-level window.
- Using the MacOS X way, desktops are just like loaded image files.
+ Under X11 on MacOS, desktops are just like loaded image files.
+ Under Cocoa on MacOS, this code is not used at all.
*/
# ifndef USE_EXTERNAL_SCREEN_GRABBER
if (desk_p)
}
# 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;
}
draw_colorbars (screen, xgwa.visual, drawable, xgwa.colormap,
0, 0, 0, 0);
XSync (dpy, False);
+ if (! file_prop) file_prop = "";
+
}
break;
break;
case GRAB_FILE:
- if (! display_file (screen, window, drawable, file, verbose_p, &geom))
+ if (*file && *file != '/') /* pathname is relative to dir. */
+ {
+ if (absfile) free (absfile);
+ absfile = malloc (strlen(dir) + strlen(file) + 10);
+ strcpy (absfile, dir);
+ if (dir[strlen(dir)-1] != '/')
+ strcat (absfile, "/");
+ strcat (absfile, file);
+ }
+ if (! display_file (screen, window, drawable,
+ (absfile ? absfile : file),
+ verbose_p, &geom))
goto COLORBARS;
file_prop = file;
break;
{
Atom a = XInternAtom (dpy, XA_XSCREENSAVER_IMAGE_FILENAME, False);
if (file_prop && *file_prop)
- XChangeProperty (dpy, window, a, XA_STRING, 8, PropModeReplace,
- (unsigned char *) file_prop, strlen(file_prop));
+ {
+ char *f2 = strdup (file_prop);
+
+ /* Take the extension off of the file name. */
+ /* Duplicated in utils/grabclient.c. */
+ char *slash = strrchr (f2, '/');
+ char *dot = strrchr ((slash ? slash : f2), '.');
+ if (dot) *dot = 0;
+ /* Replace slashes with newlines */
+ /* while ((dot = strchr(f2, '/'))) *dot = '\n'; */
+ /* Replace slashes with spaces */
+ /* while ((dot = strchr(f2, '/'))) *dot = ' '; */
+
+ XChangeProperty (dpy, window, a, XA_STRING, 8, PropModeReplace,
+ (unsigned char *) f2, strlen(f2));
+ free (f2);
+ }
else
XDeleteProperty (dpy, window, a);
XDeleteProperty (dpy, window, a);
}
+ if (absfile) free (absfile);
XSync (dpy, False);
}
memset (&P, 0, sizeof(P));
P.db = db;
- load_init_file (&P);
+ load_init_file (dpy, &P);
progname = argv[0] = oprogname;