-/* xscreensaver, Copyright (c) 1992-2006 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-2016 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
same API as this program (utils/grabclient.c).
*/
+/* This code is a mess. There's two decades of history in this file.
+ There are several distinct paths through this file depending on what
+ platform it's being compiled for:
+
+
+ X11 execution path:
+
+ load_image_async CB
+ load_random_image_x11
+ fork_exec_cb
+ "xscreensaver-getimage 0xWINDOW 0xPIXMAP"
+ "xscreensaver-getimage-file --name /DIR"
+ draw_colorbars
+ XPutImage
+ XtAppAddInput xscreensaver_getimage_cb
+ ...
+ xscreensaver_getimage_cb
+ get_name_from_xprops
+ get_original_geometry_from_xprops
+ CB name, geom, closure
+
+
+ MacOS execution path:
+
+ load_image_async CB
+ load_random_image_cocoa
+ osx_grab_desktop_image (grabclient-osx.m, MacOS version)
+ copy_framebuffer_to_ximage
+ XPutImage
+ draw_colorbars
+ osx_load_image_file_async
+ open_image_name_pipe
+ "xscreensaver-getimage-file --name /DIR"
+ XtAppAddInput xscreensaver_getimage_file_cb
+ ...
+ xscreensaver_getimage_file_cb
+ osx_load_image_file
+ CB name, geom, closure
+
+
+ iOS execution path:
+
+ load_image_async CB
+ load_random_image_cocoa
+ osx_grab_desktop_image (grabclient-osx.m, iOS version)
+ CGWindowListCreateImage
+ jwxyz_draw_NSImage_or_CGImage
+ draw_colorbars
+ ios_load_random_image
+ ios_load_random_image_cb
+ jwxyz_draw_NSImage_or_CGImage
+ CB name, geom, closure
+
+
+ Andrid execution path:
+
+ load_image_async CB
+ load_random_image_android
+ jwxyz_load_random_image (jwxyz-android.c)
+ XPutImage
+ draw_colorbars
+ CB name, geom, closure
+ */
+
#include "utils.h"
#include "grabscreen.h"
#include "resources.h"
+#include "yarandom.h"
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
# include "jwxyz.h"
# include "colorbars.h"
#else /* !HAVE_COCOA -- real Xlib */
# include <X11/Intrinsic.h> /* for XtInputId, etc */
#endif /* !HAVE_COCOA */
+#include <sys/stat.h>
+
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
static void print_loading_msg (Screen *, Window);
-#ifndef HAVE_COCOA
+
+/* Used for pipe callbacks in X11 or OSX mode.
+ X11: this is the xscreensaver_getimage_cb closure,
+ when waiting on the fork of "xscreensaver-getimage"
+ OSX: this is the xscreensaver_getimage_file_cb closure,
+ when waiting on the fork of "xscreensaver-getimage-file"
+ */
+typedef struct {
+ void (*callback) (Screen *, Window, Drawable,
+ const char *name, XRectangle *geom, void *closure);
+ Screen *screen;
+ Window window;
+ Drawable drawable;
+ void *closure;
+ XtInputId pipe_id;
+ FILE *pipe;
+
+# if !defined(USE_IPHONE) && !defined(HAVE_COCOA) /* Real X11 */
+ pid_t pid;
+# endif
+
+# if !defined(USE_IPHONE) && defined(HAVE_COCOA) /* Desktop OSX */
+ char *directory;
+# endif
+
+} xscreensaver_getimage_data;
+
+
+#if !defined(HAVE_COCOA) && !defined(HAVE_ANDROID) /* Real X11 */
static Bool error_handler_hit_p = False;
}
+/* Read the image's original name off of the window's X properties.
+ Used only when running "real" X11, not jwxyz.
+ */
static char *
-get_name (Display *dpy, Window window)
+get_name_from_xprops (Display *dpy, Window window)
{
Atom type;
int format;
}
+/* Read the image's original geometry off of the window's X properties.
+ Used only when running "real" X11, not jwxyz.
+ */
static Bool
-get_geometry (Display *dpy, Window window, XRectangle *ret)
+get_original_geometry_from_xprops (Display *dpy, Window window, XRectangle *ret)
{
Atom type;
int format;
/* Allegedly, BSD 4.3 didn't have putenv(), but nobody runs such systems
any more, right? It's not Posix, but everyone seems to have it. */
-#ifdef HAVE_PUTENV
+# ifdef HAVE_PUTENV
if (putenv (ndpy))
abort ();
-#endif /* HAVE_PUTENV */
+# 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.
+ */
}
this is due to the intermediate /bin/sh that system() uses to
parse arguments? I'm not sure. But using fork() and execvp()
here seems to close the race.
+
+ Used to execute "xscreensaver-getimage".
+ Used only when running "real" X11, not jwxyz.
*/
static void
exec_simple_command (const char *command)
}
-static void
-fork_exec_wait (const char *command)
-{
- char buf [255];
- pid_t forked;
- int status;
-
- switch ((int) (forked = fork ()))
- {
- case -1:
- sprintf (buf, "%s: couldn't fork", progname);
- perror (buf);
- return;
-
- case 0:
- exec_simple_command (command);
- exit (1); /* exits child fork */
- break;
-
- default:
- waitpid (forked, &status, 0);
- break;
- }
-}
-
-
-typedef struct {
- void (*callback) (Screen *, Window, Drawable,
- const char *name, XRectangle *geom, void *closure);
- Screen *screen;
- Window window;
- Drawable drawable;
- void *closure;
- FILE *read_pipe;
- FILE *write_pipe;
- XtInputId pipe_id;
- pid_t pid;
-} grabclient_data;
-
-
-static void finalize_cb (XtPointer closure, int *fd, XtIntervalId *id);
+static void xscreensaver_getimage_cb (XtPointer closure,
+ int *fd, XtIntervalId *id);
+/* Spawn a program, and run the callback when it finishes.
+ Used to execute "xscreensaver-getimage".
+ Used only when running "real" X11, not jwxyz.
+ */
static void
fork_exec_cb (const char *command,
Screen *screen, Window window, Drawable drawable,
void *closure)
{
XtAppContext app = XtDisplayToApplicationContext (DisplayOfScreen (screen));
- grabclient_data *data;
+ xscreensaver_getimage_data *data;
char buf [255];
pid_t forked;
+ FILE *wpipe;
int fds [2];
exit (1);
}
- data = (grabclient_data *) calloc (1, sizeof(*data));
+ data = (xscreensaver_getimage_data *) calloc (1, sizeof(*data));
data->callback = callback;
data->closure = closure;
data->screen = screen;
data->window = window;
data->drawable = drawable;
- data->read_pipe = fdopen (fds[0], "r");
- data->write_pipe = fdopen (fds[1], "w");
+ data->pipe = fdopen (fds[0], "r");
+ wpipe = fdopen (fds[1], "w"); /* Is this necessary? */
- if (!data->read_pipe || !data->write_pipe)
+ if (!data->pipe || !wpipe)
{
sprintf (buf, "%s: fdopen", progname);
perror (buf);
}
data->pipe_id =
- XtAppAddInput (app, fileno (data->read_pipe),
+ XtAppAddInput (app, fileno (data->pipe),
(XtPointer) (XtInputReadMask | XtInputExceptMask),
- finalize_cb, (XtPointer) data);
+ xscreensaver_getimage_cb, (XtPointer) data);
forked = fork ();
switch ((int) forked)
case 0: /* child */
- fclose (data->read_pipe);
- data->read_pipe = 0;
+ fclose (data->pipe);
+ data->pipe = 0;
/* clone the write pipe onto stdout so that it gets closed
when the fork exits. This will shut down the pipe and
break;
default: /* parent */
- fclose (data->write_pipe);
- data->write_pipe = 0;
+ fclose (wpipe);
data->pid = forked;
break;
}
/* Called in the parent when the forked process dies.
Runs the caller's callback, and cleans up.
+ This runs when "xscreensaver-getimage" exits.
+ Used only when running "real" X11, not jwxyz.
*/
static void
-finalize_cb (XtPointer closure, int *fd, XtIntervalId *id)
+xscreensaver_getimage_cb (XtPointer closure, int *fd, XtIntervalId *id)
{
- grabclient_data *data = (grabclient_data *) closure;
+ xscreensaver_getimage_data *data = (xscreensaver_getimage_data *) closure;
Display *dpy = DisplayOfScreen (data->screen);
char *name;
XRectangle geom = { 0, 0, 0, 0 };
XtRemoveInput (*id);
- name = get_name (dpy, data->window);
- get_geometry (dpy, data->window, &geom);
+ name = get_name_from_xprops (dpy, data->window);
+ get_original_geometry_from_xprops (dpy, data->window, &geom);
data->callback (data->screen, data->window, data->drawable,
name, &geom, data->closure);
if (name) free (name);
- fclose (data->read_pipe);
+ fclose (data->pipe);
if (data->pid) /* reap zombies */
{
/* Loads an image into the Drawable.
When grabbing desktop images, the Window will be unmapped first.
+ Used only when running "real" X11, not jwxyz.
*/
static void
-load_random_image_1 (Screen *screen, Window window, Drawable drawable,
- void (*callback) (Screen *, Window, Drawable,
- const char *name, XRectangle *geom,
- void *closure),
- void *closure,
- char **name_ret,
- XRectangle *geom_ret)
+load_random_image_x11 (Screen *screen, Window window, Drawable drawable,
+ void (*callback) (Screen *, Window, Drawable,
+ const char *name, XRectangle *geom,
+ void *closure),
+ void *closure)
{
Display *dpy = DisplayOfScreen (screen);
char *grabber = get_string_resource(dpy, "desktopGrabber", "DesktopGrabber");
XSync (dpy, True);
hack_subproc_environment (dpy);
- if (callback)
- {
- /* Start the image loading in another fork and return immediately.
- Invoke the callback function when done.
- */
- if (name_ret) abort();
- fork_exec_cb (cmd, screen, window, drawable, callback, closure);
- }
- else
- {
- /* Wait for the image to load, and return it immediately.
- */
- fork_exec_wait (cmd);
- if (name_ret)
- *name_ret = get_name (dpy, window);
- if (geom_ret)
- get_geometry (dpy, window, geom_ret);
- }
+ /* Start the image loading in another fork and return immediately.
+ Invoke the callback function when done. */
+ fork_exec_cb (cmd, screen, window, drawable, callback, closure);
free (cmd);
XSync (dpy, True);
}
-#else /* HAVE_COCOA */
+#elif defined (HAVE_COCOA) /* OSX or iOS */
+
+# ifndef USE_IPHONE /* HAVE_COCOA && !USE_IPHONE -- desktop OSX */
+
+# 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);
+
+ /* /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);
+
+ 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;
}
+
+ strcpy (s, "'");
+ s += strlen (s);
+
*s = 0;
FILE *pipe = popen (cmd, "r");
}
-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)
+xscreensaver_getimage_file_cb (XtPointer closure, int *source, XtInputId *id)
{
/* This is not called from a signal handler, so doing stuff here is fine.
*/
- struct pipe_closure *clo2 = (struct pipe_closure *) closure;
+ xscreensaver_getimage_data *clo2 = (xscreensaver_getimage_data *) 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;
- XtRemoveInput (clo2->id);
- clo2->id = 0;
+ XtRemoveInput (clo2->pipe_id);
+ clo2->pipe_id = 0;
/* strip trailing newline */
int L = strlen(buf);
Display *dpy = DisplayOfScreen (clo2->screen);
XRectangle geom;
- if (! osx_load_image_file (clo2->screen, clo2->xwindow, clo2->drawable,
- buf, &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->window, clo2->drawable,
+ (absfile ? absfile : buf), &geom)) {
/* unable to load image - draw colorbars
*/
XWindowAttributes xgwa;
- XGetWindowAttributes (dpy, clo2->xwindow, &xgwa);
+ XGetWindowAttributes (dpy, clo2->window, &xgwa);
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);
geom.height = h;
}
- clo2->callback (clo2->screen, clo2->xwindow, clo2->drawable, buf, &geom,
+ /* Take the extension off of the file name. */
+ /* Duplicated in driver/xscreensaver-getimage.c. */
+ if (*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->window, clo2->drawable, buf, &geom,
clo2->closure);
clo2->callback = 0;
+ free (clo2->directory);
+ free (clo2);
+}
+
+
+# else /* HAVE_COCOA && USE_IPHONE -- iOS */
+
+/* Callback for ios_load_random_image(), called after we have loaded an
+ image from the iOS device's Photo Library. See grabclient-ios.m.
+ */
+static void
+ios_load_random_image_cb (void *uiimage, const char *filename,
+ int width, int height, void *closure)
+{
+ xscreensaver_getimage_data *clo2 = (xscreensaver_getimage_data *) 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->window, &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->window, clo2->drawable,
+ filename, &geom, clo2->closure);
+ clo2->callback = 0;
free (clo2);
}
+# endif /* HAVE_COCOA && USE_IPHONE */
+
static void
osx_load_image_file_async (Screen *screen, Window xwindow, Drawable drawable,
void *closure),
void *closure)
{
-#if 0 /* do it synchronously */
-
- FILE *pipe = open_image_name_pipe (dir);
- char buf[10240];
- *buf = 0;
- fgets (buf, sizeof(buf)-1, pipe);
- pclose (pipe);
-
- /* strip trailing newline */
- int L = strlen(buf);
- while (L > 0 && (buf[L-1] == '\r' || buf[L-1] == '\n'))
- buf[--L] = 0;
-
- XRectangle geom;
- if (! osx_load_image_file (screen, xwindow, drawable, buf, &geom)) {
- /* draw colorbars */
- abort();
- }
- callback (screen, xwindow, drawable, buf, &geom, closure);
-
-#else /* do it asynchronously */
+ xscreensaver_getimage_data *clo2 =
+ (xscreensaver_getimage_data *) calloc (1, sizeof(*clo2));
- 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->window = xwindow;
clo2->drawable = drawable;
clo2->callback = callback;
clo2->closure = closure;
-#endif
+
+# ifndef USE_IPHONE /* Desktop OSX */
+ clo2->directory = strdup (dir);
+ clo2->pipe = open_image_name_pipe (dir);
+ clo2->pipe_id = XtAppAddInput (XtDisplayToApplicationContext (
+ DisplayOfScreen (screen)),
+ fileno (clo2->pipe),
+ (XtPointer) (XtInputReadMask | XtInputExceptMask),
+ xscreensaver_getimage_file_cb, (XtPointer) clo2);
+# else /* USE_IPHONE */
+ ios_load_random_image (ios_load_random_image_cb, clo2);
+# endif /* USE_IPHONE */
}
/* Loads an image into the Drawable, returning once the image is loaded.
*/
static void
-load_random_image_1 (Screen *screen, Window window, Drawable drawable,
- void (*callback) (Screen *, Window, Drawable,
- const char *name, XRectangle *geom,
- void *closure),
- void *closure,
- char **name_ret,
- XRectangle *geom_ret)
+load_random_image_cocoa (Screen *screen, Window window, Drawable drawable,
+ void (*callback) (Screen *, Window, Drawable,
+ const char *name, XRectangle *geom,
+ void *closure),
+ void *closure)
{
Display *dpy = DisplayOfScreen (screen);
XWindowAttributes xgwa;
Bool filep = get_boolean_resource (dpy, "chooseRandomImages", "Boolean");
const char *dir = 0;
Bool done = False;
- XRectangle geom_ret_2;
- char *name_ret_2 = 0;
-
- if (callback) {
- geom_ret = &geom_ret_2;
- name_ret = &name_ret_2;
- }
+ XRectangle geom;
+ char *name = 0;
+
+ if (!drawable) abort();
XGetWindowAttributes (dpy, window, &xgwa);
{
xgwa.height = h;
}
- if (name_ret)
- *name_ret = 0;
-
- if (geom_ret) {
- geom_ret->x = 0;
- geom_ret->y = 0;
- geom_ret->width = xgwa.width;
- geom_ret->height = xgwa.height;
- }
+ geom.x = 0;
+ geom.y = 0;
+ geom.width = xgwa.width;
+ geom.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 */
}
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)) {
+ name = 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 we got here, we loaded synchronously, so we're done. */
+ callback (screen, window, drawable, name, &geom, closure);
+ if (name) free (name);
+}
+
+
+#elif defined(HAVE_ANDROID)
+
+/* Loads an image into the Drawable, returning once the image is loaded.
+ */
+static void
+load_random_image_android (Screen *screen, Window window, Drawable drawable,
+ void (*callback) (Screen *, Window, Drawable,
+ const char *name,
+ XRectangle *geom, void *closure),
+ void *closure)
+{
+ Display *dpy = DisplayOfScreen (screen);
+ XWindowAttributes xgwa;
+ XRectangle geom;
+ char *name = 0;
+ char *data = 0;
+ int width = 0;
+ int height = 0;
+
+ if (!drawable) abort();
+
+ XGetWindowAttributes (dpy, window, &xgwa);
+ {
+ Window r;
+ int x, y;
+ unsigned int w, h, bbw, d;
+ XGetGeometry (dpy, drawable, &r, &x, &y, &w, &h, &bbw, &d);
+ xgwa.width = w;
+ xgwa.height = h;
}
+
+ geom.x = 0;
+ geom.y = 0;
+ geom.width = xgwa.width;
+ geom.height = xgwa.height;
+
+ data = jwxyz_load_random_image (dpy, &width, &height, &name);
+ if (! data)
+ draw_colorbars (screen, xgwa.visual, drawable, xgwa.colormap,
+ 0, 0, xgwa.width, xgwa.height);
+ else
+ {
+ XImage *img = XCreateImage (dpy, xgwa.visual, 32,
+ ZPixmap, 0, data, width, height, 0, 0);
+ XGCValues gcv;
+ GC gc;
+ gcv.foreground = BlackPixelOfScreen (screen);
+ gc = XCreateGC (dpy, drawable, GCForeground, &gcv);
+ XFillRectangle (dpy, drawable, gc, 0, 0, xgwa.width, xgwa.height);
+ XPutImage (dpy, drawable, gc, img, 0, 0,
+ (xgwa.width - width) / 2,
+ (xgwa.height - height) / 2,
+ width, height);
+ XDestroyImage (img);
+ XFreeGC (dpy, gc);
+ }
+
+ callback (screen, window, drawable, name, &geom, closure);
+ if (name) free (name);
}
-#endif /* HAVE_COCOA */
+#endif /* HAVE_ANDROID */
+
/* Writes the string "Loading..." in the middle of the screen.
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");
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);
void *closure),
void *closure)
{
- load_random_image_1 (screen, window, drawable, callback, closure, 0, 0);
+ if (!callback) abort();
+# if defined(HAVE_COCOA)
+ load_random_image_cocoa (screen, window, drawable, callback, closure);
+# elif defined(HAVE_ANDROID)
+ load_random_image_android (screen, window, drawable, callback, closure);
+# else /* real X11 */
+ load_random_image_x11 (screen, window, drawable, callback, closure);
+# endif
}
struct async_load_state {