X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=utils%2Fgrabclient.c;h=ff90820fb4ff0b72bfe9a0e9dfef76711bccde86;hb=d5186197bc394e10a4402f7f6d23fbb14103bc50;hp=54396c765616bdd51f0e84f84178c803c2539d84;hpb=5f1f12f2a37da634000f96d18d59cc73a8814ef7;p=xscreensaver diff --git a/utils/grabclient.c b/utils/grabclient.c index 54396c76..ff90820f 100644 --- a/utils/grabclient.c +++ b/utils/grabclient.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1992-2010 Jamie Zawinski +/* xscreensaver, Copyright (c) 1992-2014 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" @@ -511,26 +512,63 @@ 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 + +# define BACKSLASH(c) \ + (! ((c >= 'a' && c <= 'z') || \ + (c >= 'A' && c <= 'Z') || \ + (c >= '0' && c <= '9') || \ + c == '.' || c == '_' || c == '-' || c == '+' || c == '/')) + /* 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! */ static FILE * open_image_name_pipe (const char *dir) { - char *cmd = malloc (strlen(dir) * 2 + 100); char *s; - strcpy (cmd, "xscreensaver-getimage-file --name "); - s = cmd + strlen (cmd); + +# ifdef HAVE_COCOA + /* /bin/sh on OS X 10.10 wipes out the PATH. */ + const char *path = getenv("PATH"); + char *cmd = s = malloc ((strlen(dir) + strlen(path)) * 2 + 100); + strcpy (s, "/bin/sh -c 'export PATH="); + s += strlen (s); + while (*path) { + char c = *path++; + if (BACKSLASH(c)) *s++ = '\\'; + *s++ = c; + } + strcpy (s, "; "); + s += strlen (s); +# else + char *cmd = s = malloc (strlen(dir) * 2 + 100); +# endif + + strcpy (s, "xscreensaver-getimage-file --name "); + s += strlen (s); while (*dir) { char c = *dir++; - /* put a backslash in front of any character that might confuse sh. */ - if (! ((c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || - (c >= '0' && c <= '9') || - c == '.' || c == '_' || c == '-' || c == '+' || c == '/')) - *s++ = '\\'; + if (BACKSLASH(c)) *s++ = '\\'; *s++ = c; } +# ifdef HAVE_COCOA + strcpy (s, "'"); + s += strlen (s); +# endif *s = 0; FILE *pipe = popen (cmd, "r"); @@ -539,19 +577,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) { @@ -559,6 +584,9 @@ 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; + *buf = 0; fgets (buf, sizeof(buf)-1, clo2->pipe); pclose (clo2->pipe); clo2->pipe = 0; @@ -573,8 +601,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; @@ -582,13 +619,13 @@ pipe_cb (XtPointer closure, int *source, XtInputId *id) Window r; int x, y; unsigned int w, h, bbw, d; - struct stat *st; + 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)) + else if (! stat (buf, &st)) fprintf (stderr, "%s: %s: unparsable\n", progname, buf); else { @@ -605,13 +642,86 @@ 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, + int width, int height, void *closure) +{ + struct pipe_closure *clo2 = (struct pipe_closure *) closure; + Display *dpy = DisplayOfScreen (clo2->screen); + XRectangle geom; + XWindowAttributes xgwa; + Window r; + int x, y; + unsigned int w, h, bbw, d; + int rot = 0; + + XGetWindowAttributes (dpy, clo2->xwindow, &xgwa); + XGetGeometry (dpy, clo2->drawable, &r, &x, &y, &w, &h, &bbw, &d); + + /* If the image is portrait and the window is landscape, or vice versa, + rotate the image. The idea is to fill up as many pixels as possible, + and assume the user will just rotate their phone until it looks right. + This makes "decayscreen", etc. much more easily viewable. + */ + if (get_boolean_resource (dpy, "rotateImages", "RotateImages")) { + if ((width > height) != (w > h)) + rot = 5; + } + + if (uiimage) + { + jwxyz_draw_NSImage_or_CGImage (DisplayOfScreen (clo2->screen), + clo2->drawable, + True, uiimage, &geom, + rot); + } + else /* Probably means no images in the gallery. */ + { + 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, @@ -621,7 +731,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]; @@ -641,21 +751,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 } @@ -678,7 +796,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) { @@ -706,11 +824,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 */ @@ -724,22 +844,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); } } @@ -777,7 +897,7 @@ print_loading_msg (Screen *screen, Window window) fn = 0; XGetWindowAttributes (dpy, window, &xgwa); - w = XTextWidth (f, text, strlen(text)); + w = XTextWidth (f, text, (int) strlen(text)); gcv.foreground = get_pixel_resource (dpy, xgwa.colormap, "foreground", "Foreground"); @@ -788,7 +908,7 @@ print_loading_msg (Screen *screen, Window window) XDrawImageString (dpy, window, gc, (xgwa.width - w) / 2, (xgwa.height - (f->ascent + f->descent)) / 2 + f->ascent, - text, strlen(text)); + text, (int) strlen(text)); XFreeFont (dpy, f); XFreeGC (dpy, gc); XSync (dpy, False);