From http://www.jwz.org/xscreensaver/xscreensaver-5.22.tar.gz
[xscreensaver] / utils / grabclient.c
index 438197e80da1ff1eb2b4db6dcbb9d8e5a47c7cae..082f1f167a7e5a62dafda935e156b4a9da99e510 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992-2010 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-2013 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
@@ -21,6 +21,7 @@
 #include "utils.h"
 #include "grabscreen.h"
 #include "resources.h"
+#include "yarandom.h"
 
 #ifdef HAVE_COCOA
 # include "jwxyz.h"
@@ -511,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!
  */
@@ -539,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)
 {
@@ -559,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;
@@ -573,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;
@@ -605,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,
@@ -621,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];
@@ -641,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
 }
 
 
@@ -678,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) {
@@ -706,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 */
@@ -724,10 +808,11 @@ 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)
@@ -738,6 +823,7 @@ load_random_image_1 (Screen *screen, Window window, Drawable drawable,
     /* 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);
   }
 }