X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=utils%2Fgrabclient.c;h=082f1f167a7e5a62dafda935e156b4a9da99e510;hb=4ade52359b6eba3621566dac79793a33aa4c915f;hp=3589ad9821d6af4d6f983faf4e99799646861f79;hpb=6b1c86cf395f59389e4ece4ea8f4bea2c332745b;p=xscreensaver diff --git a/utils/grabclient.c b/utils/grabclient.c index 3589ad98..082f1f16 100644 --- a/utils/grabclient.c +++ b/utils/grabclient.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1992-2008 Jamie Zawinski +/* xscreensaver, Copyright (c) 1992-2013 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -21,6 +21,7 @@ #include "utils.h" #include "grabscreen.h" #include "resources.h" +#include "yarandom.h" #ifdef HAVE_COCOA # include "jwxyz.h" @@ -31,6 +32,8 @@ # include /* for XtInputId, etc */ #endif /* !HAVE_COCOA */ +#include + #ifdef HAVE_UNISTD_H # include #endif @@ -247,6 +250,11 @@ hack_subproc_environment (Display *dpy) if (putenv (ndpy)) abort (); #endif /* HAVE_PUTENV */ + + /* don't free (ndpy) -- some implementations of putenv (BSD 4.4, + glibc 2.0) copy the argument, but some (libc4,5, glibc 2.1.2, MacOS) + do not. So we must leak it (and/or the previous setting). Yay. + */ } @@ -504,6 +512,21 @@ load_random_image_1 (Screen *screen, Window window, Drawable drawable, #else /* HAVE_COCOA */ +struct pipe_closure { + FILE *pipe; + XtInputId id; + Screen *screen; + Window xwindow; + Drawable drawable; + char *directory; + void (*callback) (Screen *, Window, Drawable, + const char *name, XRectangle *geom, + void *closure); + void *closure; +}; + +# ifndef USE_IPHONE + /* Gets the name of an image file to load by running xscreensaver-getimage-file at the end of a pipe. This can be very slow! */ @@ -532,19 +555,6 @@ open_image_name_pipe (const char *dir) } -struct pipe_closure { - FILE *pipe; - XtInputId id; - Screen *screen; - Window xwindow; - Drawable drawable; - void (*callback) (Screen *, Window, Drawable, - const char *name, XRectangle *geom, - void *closure); - void *closure; -}; - - static void pipe_cb (XtPointer closure, int *source, XtInputId *id) { @@ -552,6 +562,8 @@ pipe_cb (XtPointer closure, int *source, XtInputId *id) */ struct pipe_closure *clo2 = (struct pipe_closure *) closure; char buf[10240]; + const char *dir = clo2->directory; + char *absfile = 0; fgets (buf, sizeof(buf)-1, clo2->pipe); pclose (clo2->pipe); clo2->pipe = 0; @@ -566,8 +578,17 @@ pipe_cb (XtPointer closure, int *source, XtInputId *id) Display *dpy = DisplayOfScreen (clo2->screen); XRectangle geom; + if (*buf && *buf != '/') /* pathname is relative to dir. */ + { + absfile = malloc (strlen(dir) + strlen(buf) + 10); + strcpy (absfile, dir); + if (dir[strlen(dir)-1] != '/') + strcat (absfile, "/"); + strcat (absfile, buf); + } + if (! osx_load_image_file (clo2->screen, clo2->xwindow, clo2->drawable, - buf, &geom)) { + (absfile ? absfile : buf), &geom)) { /* unable to load image - draw colorbars */ XWindowAttributes xgwa; @@ -575,6 +596,21 @@ pipe_cb (XtPointer closure, int *source, XtInputId *id) Window r; int x, y; unsigned int w, h, bbw, d; + struct stat st; + + /* Log something to syslog so we can tell the difference between + corrupted images and broken symlinks. */ + if (!*buf) + fprintf (stderr, "%s: no image filename found\n", progname); + else if (! stat (buf, &st)) + fprintf (stderr, "%s: %s: unparsable\n", progname, buf); + else + { + char buf2[2048]; + sprintf (buf2, "%.255s: %.1024s", progname, buf); + perror (buf2); + } + XGetGeometry (dpy, clo2->drawable, &r, &x, &y, &w, &h, &bbw, &d); draw_colorbars (clo2->screen, xgwa.visual, clo2->drawable, xgwa.colormap, 0, 0, w, h); @@ -583,13 +619,73 @@ pipe_cb (XtPointer closure, int *source, XtInputId *id) geom.height = h; } + /* Take the extension off of the file name. */ + /* Duplicated in driver/xscreensaver-getimage.c. */ + if (buf && *buf) + { + char *slash = strrchr (buf, '/'); + char *dot = strrchr ((slash ? slash : buf), '.'); + if (dot) *dot = 0; + /* Replace slashes with newlines */ + /* while (dot = strchr(buf, '/')) *dot = '\n'; */ + /* Replace slashes with spaces */ + while ((dot = strchr(buf, '/'))) *dot = ' '; + } + + if (absfile) free (absfile); clo2->callback (clo2->screen, clo2->xwindow, clo2->drawable, buf, &geom, clo2->closure); clo2->callback = 0; + free (clo2->directory); free (clo2); } +# else /* USE_IPHONE */ + +/* Callback for ios_load_random_image(), called after we have loaded an + image from the iOS device's Photo Library. See iosgrabimage.m. + */ +static void +ios_load_random_image_cb (void *uiimage, const char *filename, void *closure) +{ + struct pipe_closure *clo2 = (struct pipe_closure *) closure; + Display *dpy = DisplayOfScreen (clo2->screen); + XRectangle geom; + + if (uiimage) + { + jwxyz_draw_NSImage_or_CGImage (DisplayOfScreen (clo2->screen), + clo2->drawable, + True, uiimage, &geom, + 0); + } + else /* Probably means no images in the gallery. */ + { + XWindowAttributes xgwa; + Window r; + int x, y; + unsigned int w, h, bbw, d; + XGetWindowAttributes (dpy, clo2->xwindow, &xgwa); + XGetGeometry (dpy, clo2->drawable, &r, &x, &y, &w, &h, &bbw, &d); + draw_colorbars (clo2->screen, xgwa.visual, clo2->drawable, xgwa.colormap, + 0, 0, w, h); + geom.x = geom.y = 0; + geom.width = w; + geom.height = h; + filename = 0; + } + + clo2->callback (clo2->screen, clo2->xwindow, clo2->drawable, + filename, &geom, clo2->closure); + clo2->callback = 0; + if (clo2->directory) free (clo2->directory); + free (clo2); +} + +# endif /* USE_IPHONE */ + + static void osx_load_image_file_async (Screen *screen, Window xwindow, Drawable drawable, const char *dir, @@ -599,7 +695,7 @@ osx_load_image_file_async (Screen *screen, Window xwindow, Drawable drawable, void *closure), void *closure) { -#if 0 /* do it synchronously */ +# if 0 /* do it synchronously */ FILE *pipe = open_image_name_pipe (dir); char buf[10240]; @@ -619,21 +715,29 @@ osx_load_image_file_async (Screen *screen, Window xwindow, Drawable drawable, } callback (screen, xwindow, drawable, buf, &geom, closure); -#else /* do it asynchronously */ +# else /* do it asynchronously */ - Display *dpy = DisplayOfScreen (screen); struct pipe_closure *clo2 = (struct pipe_closure *) calloc (1, sizeof(*clo2)); - clo2->pipe = open_image_name_pipe (dir); - clo2->id = XtAppAddInput (XtDisplayToApplicationContext (dpy), - fileno (clo2->pipe), - (XtPointer) (XtInputReadMask | XtInputExceptMask), - pipe_cb, (XtPointer) clo2); + clo2->screen = screen; clo2->xwindow = xwindow; clo2->drawable = drawable; clo2->callback = callback; clo2->closure = closure; -#endif + +# ifndef USE_IPHONE + clo2->directory = strdup (dir); + clo2->pipe = open_image_name_pipe (dir); + clo2->id = XtAppAddInput (XtDisplayToApplicationContext ( + DisplayOfScreen (screen)), + fileno (clo2->pipe), + (XtPointer) (XtInputReadMask | XtInputExceptMask), + pipe_cb, (XtPointer) clo2); +# else /* USE_IPHONE */ + ios_load_random_image (ios_load_random_image_cb, clo2); +# endif /* USE_IPHONE */ + +# endif } @@ -656,7 +760,7 @@ load_random_image_1 (Screen *screen, Window window, Drawable drawable, Bool done = False; XRectangle geom_ret_2; char *name_ret_2 = 0; - + if (!drawable) abort(); if (callback) { @@ -684,11 +788,13 @@ load_random_image_1 (Screen *screen, Window window, Drawable drawable, geom_ret->height = xgwa.height; } +# ifndef USE_IPHONE if (filep) dir = get_string_resource (dpy, "imageDirectory", "ImageDirectory"); if (!dir || !*dir) filep = False; +# endif /* ! USE_IPHONE */ if (deskp && filep) { deskp = !(random() & 5); /* if both, desktop 1/5th of the time */ @@ -702,22 +808,22 @@ load_random_image_1 (Screen *screen, Window window, Drawable drawable, } if (deskp && !done) { - osx_grab_desktop_image (screen, window, drawable); - if (name_ret) - *name_ret = strdup ("desktop"); - done = True; + if (osx_grab_desktop_image (screen, window, drawable, &geom_ret_2)) { + if (name_ret) + *name_ret = strdup ("desktop"); + done = True; + } } - if (! done) { + if (! done) draw_colorbars (screen, xgwa.visual, drawable, xgwa.colormap, 0, 0, xgwa.width, xgwa.height); - done = True; - } if (callback) { /* If we got here, we loaded synchronously even though they wanted async. */ callback (screen, window, drawable, name_ret_2, &geom_ret_2, closure); + if (name_ret_2) free (name_ret_2); } }