From http://www.jwz.org/xscreensaver/xscreensaver-5.35.tar.gz
[xscreensaver] / OSX / osxgrabscreen.m
index f42ad34bc270b225534fcc76b8497e070ba77355..c7f4f15b686902b3185744abf1f3f06eef74c001 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992-2010 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-2012 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
  */
 
 /* This is the OSX implementation of desktop-grabbing and image-loading.
+   This code is invoked by "utils/grabclient.c", which is linked directly
+   in to each screen saver bundle.
+
+   X11-based builds of the savers do not use this code (even on MacOS).
+   This is used only by the Cocoa build of the savers.
  */
 
 #import <stdlib.h>
 #import <stdint.h>
-#import <Cocoa/Cocoa.h>
-#import "jwxyz.h"
+#ifndef USE_IPHONE
+# import <Cocoa/Cocoa.h>
+#else
+# import "SaverRunner.h"
+#endif
+#import "jwxyz-cocoa.h"
 #import "grabscreen.h"
 #import "colorbars.h"
 #import "resources.h"
 #import "usleep.h"
 
 
+#ifdef USE_IPHONE
+# define NSImage UIImage
+#endif
+
+
 #ifndef  MAC_OS_X_VERSION_10_6
 # define MAC_OS_X_VERSION_10_6 1060  /* undefined in 10.4 SDK, grr */
 #endif
@@ -127,8 +141,9 @@ copy_framebuffer_to_ximage (CGDirectDisplayID cgdpy, XImage *xim,
 
 /* Loads an image into the Drawable, returning once the image is loaded.
  */
-void
-osx_grab_desktop_image (Screen *screen, Window xwindow, Drawable drawable)
+Bool
+osx_grab_desktop_image (Screen *screen, Window xwindow, Drawable drawable,
+                        XRectangle *geom_ret)
 {
   Display *dpy = DisplayOfScreen (screen);
   NSView *nsview = jwxyz_window_view (xwindow);
@@ -216,9 +231,49 @@ osx_grab_desktop_image (Screen *screen, Window xwindow, Drawable drawable)
   // Splat the XImage onto the target drawable (probably the window)
   // and free the bits.
   //
-  GC gc = 0;
+  XGCValues gcv;
+  GC gc = XCreateGC (dpy, drawable, 0, &gcv);
   XPutImage (dpy, drawable, gc, xim, 0, 0, 0, 0, xim->width, xim->height);
+  XFreeGC (dpy, gc);
+
+  if (geom_ret) {
+    geom_ret->x = 0;
+    geom_ret->y = 0;
+    geom_ret->width  = xim->width;
+    geom_ret->height = xim->height;
+  }
+
   XDestroyImage (xim);
+  return True;
+}
+
+
+#elif defined(USE_IPHONE)
+
+       /* What a hack!
+
+           On iOS, our application delegate, SaverRunner, grabs an image
+           of itself as a UIImage before mapping the XScreenSaverView.
+           In this code, we ask SaverRunner for that UIImage, then copy
+           it to the root window.
+         */
+
+Bool
+osx_grab_desktop_image (Screen *screen, Window xwindow, Drawable drawable,
+                        XRectangle *geom_ret)
+{
+  SaverRunner *s = 
+    (SaverRunner *) [[UIApplication sharedApplication] delegate];
+  if (! s)
+    return False;
+  if (! [s isKindOfClass:[SaverRunner class]])
+    return False;
+  UIImage *img = [s screenshot];
+  if (! img)
+    return False;
+  jwxyz_draw_NSImage_or_CGImage (DisplayOfScreen (screen), drawable,
+                                 True, img, geom_ret, 0);
+  return True;
 }
 
 
@@ -233,8 +288,9 @@ osx_grab_desktop_image (Screen *screen, Window xwindow, Drawable drawable)
 
 /* Loads an image into the Drawable, returning once the image is loaded.
  */
-void
-osx_grab_desktop_image (Screen *screen, Window xwindow, Drawable drawable)
+Bool
+osx_grab_desktop_image (Screen *screen, Window xwindow, Drawable drawable,
+                        XRectangle *geom_ret)
 {
   Display *dpy = DisplayOfScreen (screen);
   NSView *nsview = jwxyz_window_view (xwindow);
@@ -281,17 +337,20 @@ osx_grab_desktop_image (Screen *screen, Window xwindow, Drawable drawable)
   // put us back above the login windows so the screensaver is visible.
   [[nsview window] setLevel:oldLevel];
 
+  if (! img) return False;
+
   // Render the grabbed CGImage into the Drawable.
-  if (img) {
-    jwxyz_draw_NSImage_or_CGImage (DisplayOfScreen (screen), drawable, 
-                                   False, img, NULL, 0);
-    CGImageRelease (img);
-  }
+  jwxyz_draw_NSImage_or_CGImage (DisplayOfScreen (screen), drawable, 
+                                 False, img, geom_ret, 0);
+  CGImageRelease (img);
+  return True;
 }
 
 #endif /* 10.5+ code */
 
 
+# ifndef USE_IPHONE
+
 /* Returns the EXIF rotation property of the image, if any.
  */
 static int
@@ -350,6 +409,9 @@ exif_rotation (const char *filename)
 # endif /* 10.5 */
 }
 
+# endif /* USE_IPHONE */
+
+
 
 /* Loads an image file and splats it onto the drawable.
    The image is drawn as large as possible while preserving its aspect ratio.
@@ -360,6 +422,10 @@ Bool
 osx_load_image_file (Screen *screen, Window xwindow, Drawable drawable,
                      const char *filename, XRectangle *geom_ret)
 {
+# ifndef USE_IPHONE
+
+  if (!filename || !*filename) return False;
+
   NSImage *img = [[NSImage alloc] initWithContentsOfFile:
                                     [NSString stringWithCString:filename
                                               encoding:NSUTF8StringEncoding]];
@@ -367,9 +433,15 @@ osx_load_image_file (Screen *screen, Window xwindow, Drawable drawable,
     return False;
 
   jwxyz_draw_NSImage_or_CGImage (DisplayOfScreen (screen), drawable, 
-                                 True, img, geom_ret, 
+                                 True, img, geom_ret,
                                  exif_rotation (filename));
   [img release];
   return True;
-}
 
+# else  /* USE_IPHONE */
+
+  /* This is handled differently: see grabclient.c and iosgrabimage.m. */
+  return False;
+
+# endif /* USE_IPHONE */
+}