X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fboxfit.c;h=3c811ca00b75b3b11c1b9216a476d1e1e94e0a86;hb=4ade52359b6eba3621566dac79793a33aa4c915f;hp=34b9d7db4d8cbff33dbb57c79266149c93f69e30;hpb=2d04c4f22466851aedb6ed0f2919d148f726b889;p=xscreensaver diff --git a/hacks/boxfit.c b/hacks/boxfit.c index 34b9d7db..3c811ca0 100644 --- a/hacks/boxfit.c +++ b/hacks/boxfit.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 2005 Jamie Zawinski +/* xscreensaver, Copyright (c) 2005-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 @@ -17,10 +17,11 @@ #include "screenhack.h" #include -#include +#include "xpm-pixmap.h" #define ALIVE 1 #define CHANGED 2 +#define UNDEAD 4 typedef struct { unsigned long fill_color; @@ -33,11 +34,12 @@ typedef struct { Window window; XWindowAttributes xgwa; GC gc; - unsigned long bg_color; + unsigned long fg_color, bg_color; int border_size; int spacing; int inc; + int mode; Bool circles_p; Bool growing_p; Bool color_horiz_p; @@ -47,33 +49,38 @@ typedef struct { int nboxes; box *boxes; + XImage *image; int ncolors; XColor *colors; + int delay; + int countdown; + + Bool done_once; + async_load_state *img_loader; + Pixmap loading_pixmap; + } state; static void reset_boxes (state *st) { - static Bool once = False; - int mode = -1; - st->nboxes = 0; st->growing_p = True; st->color_horiz_p = random() & 1; - if (once) - free_colors (st->dpy, st->xgwa.colormap, st->colors, st->ncolors); + if (st->done_once && st->colors) + free_colors (st->xgwa.screen, st->xgwa.colormap, st->colors, st->ncolors); - if (!once) + if (!st->done_once) { - char *s = get_string_resource ("mode", "Mode"); + char *s = get_string_resource (st->dpy, "mode", "Mode"); if (!s || !*s || !strcasecmp (s, "random")) - mode = -1; + st->mode = -1; else if (!strcasecmp (s, "squares") || !strcasecmp (s, "square")) - mode = 0; + st->mode = 0; else if (!strcasecmp (s, "circles") || !strcasecmp (s, "circle")) - mode = 1; + st->mode = 1; else { fprintf (stderr, @@ -83,41 +90,84 @@ reset_boxes (state *st) } } - if (mode == -1) + if (st->mode == -1) st->circles_p = random() & 1; else - st->circles_p = (mode == 1); + st->circles_p = (st->mode == 1); - once = True; + st->done_once = True; - st->ncolors = get_integer_resource ("colors", "Colors"); /* re-get this */ - make_smooth_colormap (st->dpy, st->xgwa.visual, st->xgwa.colormap, - st->colors, &st->ncolors, True, 0, False); - XClearWindow (st->dpy, st->window); + if (st->image || get_boolean_resource (st->dpy, "grab", "Boolean")) + { + if (st->image) XDestroyImage (st->image); + st->image = 0; + + if (st->loading_pixmap) abort(); + if (st->img_loader) abort(); + if (!get_boolean_resource (st->dpy, "peek", "Boolean")) + st->loading_pixmap = XCreatePixmap (st->dpy, st->window, + st->xgwa.width, st->xgwa.height, + st->xgwa.depth); + + XClearWindow (st->dpy, st->window); + st->img_loader = load_image_async_simple (0, st->xgwa.screen, + st->window, + (st->loading_pixmap + ? st->loading_pixmap + : st->window), + 0, 0); + } + else + { + st->ncolors = get_integer_resource (st->dpy, "colors", "Colors"); /* re-get */ + if (st->ncolors < 1) st->ncolors = 1; + make_smooth_colormap (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap, + st->colors, &st->ncolors, True, 0, False); + if (st->ncolors < 1) abort(); + XClearWindow (st->dpy, st->window); + } } -state * -init_boxes (Display *dpy, Window window) +static void +reshape_boxes (state *st) +{ + int i; + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + for (i = 0; i < st->nboxes; i++) + { + box *b = &st->boxes[i]; + b->flags |= CHANGED; + } +} + +static void * +boxfit_init (Display *dpy, Window window) { XGCValues gcv; state *st = (state *) calloc (1, sizeof (*st)); st->dpy = dpy; st->window = window; + st->delay = get_integer_resource (dpy, "delay", "Integer"); XGetWindowAttributes (st->dpy, st->window, &st->xgwa); - XSelectInput (dpy, window, st->xgwa.your_event_mask | ExposureMask); +/* XSelectInput (dpy, window, st->xgwa.your_event_mask | ExposureMask);*/ - st->ncolors = get_integer_resource ("colors", "Colors"); - if (st->ncolors < 1) st->ncolors = 1; - st->colors = (XColor *) malloc (sizeof(XColor) * st->ncolors); + if (! get_boolean_resource (dpy, "grab", "Boolean")) + { + st->ncolors = get_integer_resource (dpy, "colors", "Colors"); + if (st->ncolors < 1) st->ncolors = 1; + st->colors = (XColor *) malloc (sizeof(XColor) * st->ncolors); + } - st->inc = get_integer_resource ("growBy", "GrowBy"); - st->spacing = get_integer_resource ("spacing", "Spacing"); - st->border_size = get_integer_resource ("borderSize", "BorderSize"); - st->bg_color = get_pixel_resource ("background", "Background", - st->dpy, st->xgwa.colormap); + st->inc = get_integer_resource (dpy, "growBy", "GrowBy"); + st->spacing = get_integer_resource (dpy, "spacing", "Spacing"); + st->border_size = get_integer_resource (dpy, "borderSize", "BorderSize"); + st->fg_color = get_pixel_resource (st->dpy, st->xgwa.colormap, + "foreground", "Foreground"); + st->bg_color = get_pixel_resource (st->dpy, st->xgwa.colormap, + "background", "Background"); if (st->inc < 1) st->inc = 1; if (st->border_size < 0) st->border_size = 0; @@ -125,7 +175,7 @@ init_boxes (Display *dpy, Window window) gcv.background = st->bg_color; st->gc = XCreateGC (st->dpy, st->window, GCBackground|GCLineWidth, &gcv); - st->box_count = get_integer_resource ("boxCount", "BoxCount"); + st->box_count = get_integer_resource (dpy, "boxCount", "BoxCount"); if (st->box_count < 1) st->box_count = 1; st->nboxes = 0; @@ -134,20 +184,10 @@ init_boxes (Display *dpy, Window window) reset_boxes (st); + reshape_boxes (st); return st; } -static void -reshape_boxes (state *st) -{ - int i; - XGetWindowAttributes (st->dpy, st->window, &st->xgwa); - for (i = 0; i < st->nboxes; i++) - { - box *b = &st->boxes[i]; - b->flags |= CHANGED; - } -} static Bool @@ -214,7 +254,7 @@ box_collides_p (state *st, box *a, int pad) } -static void +static unsigned int grow_boxes (state *st) { int inc2 = st->inc + st->spacing + st->border_size; @@ -262,9 +302,9 @@ grow_boxes (state *st) } a = &st->boxes[st->nboxes-1]; - a->flags |= CHANGED; + a->flags = CHANGED; - for (i = 0; i < 10000; i++) + for (i = 0; i < 100; i++) { a->x = inc2 + (random() % (st->xgwa.width - inc2)); a->y = inc2 + (random() % (st->xgwa.height - inc2)); @@ -284,25 +324,30 @@ grow_boxes (state *st) { st->nboxes--; /* go into "fade out" mode now. */ st->growing_p = False; - - XSync (st->dpy, False); - sleep (1); - - break; + return 2000000; /* make customizable... */ } /* Pick colors for this box */ - { - int n = (st->color_horiz_p - ? (a->x * st->ncolors / st->xgwa.width) - : (a->y * st->ncolors / st->xgwa.height)); - a->fill_color = st->colors [n % st->ncolors].pixel; - } + if (st->image) + { + int w = st->image->width; + int h = st->image->height; + a->fill_color = XGetPixel (st->image, a->x % w, a->y % h); + } + else + { + int n = (st->color_horiz_p + ? (a->x * st->ncolors / st->xgwa.width) + : (a->y * st->ncolors / st->xgwa.height)); + a->fill_color = st->colors [n % st->ncolors].pixel; + } } + + return st->delay; } -static void +static unsigned int shrink_boxes (state *st) { int i; @@ -326,8 +371,12 @@ shrink_boxes (state *st) remaining++; } - if (remaining == 0) + if (remaining == 0) { reset_boxes (st); + return 1000000; + } else { + return st->delay; + } } @@ -339,34 +388,33 @@ draw_boxes (state *st) { box *b = &st->boxes[i]; + if (b->flags & UNDEAD) continue; + if (! (b->flags & CHANGED)) continue; + b->flags &= ~CHANGED; + if (!st->growing_p) { /* When shrinking, black out an area outside of the border before re-drawing the box. */ - XSetForeground (st->dpy, st->gc, st->bg_color); - XSetLineAttributes (st->dpy, st->gc, - (st->inc + st->border_size) * 2, - LineSolid, CapButt, JoinMiter); + int margin = st->inc + st->border_size; + XSetForeground (st->dpy, st->gc, st->bg_color); if (st->circles_p) - XDrawArc (st->dpy, st->window, st->gc, - b->x, b->y, - (b->w > 0 ? b->w : 1), - (b->h > 0 ? b->h : 1), + XFillArc (st->dpy, st->window, st->gc, + b->x - margin, b->y - margin, + b->w + (margin*2), b->h + (margin*2), 0, 360*64); else - XDrawRectangle (st->dpy, st->window, st->gc, - b->x, b->y, - (b->w > 0 ? b->w : 1), - (b->h > 0 ? b->h : 1)); - XSetLineAttributes (st->dpy, st->gc, st->border_size, - LineSolid, CapButt, JoinMiter); + XFillRectangle (st->dpy, st->window, st->gc, + b->x - margin, b->y - margin, + b->w + (margin*2), b->h + (margin*2)); + + if (b->w <= 0 || b->h <= 0) + b->flags |= UNDEAD; /* really very dead now */ } if (b->w <= 0 || b->h <= 0) continue; - if (! (b->flags & CHANGED)) continue; - b->flags &= ~CHANGED; XSetForeground (st->dpy, st->gc, b->fill_color); @@ -378,8 +426,10 @@ draw_boxes (state *st) if (st->border_size > 0) { - unsigned long bd = st->colors [(b->fill_color + st->ncolors/2) - % st->ncolors].pixel; + unsigned int bd = (st->image + ? st->fg_color + : st->colors [(b->fill_color + st->ncolors/2) + % st->ncolors].pixel); XSetForeground (st->dpy, st->gc, bd); if (st->circles_p) XDrawArc (st->dpy, st->window, st->gc, b->x, b->y, b->w, b->h, @@ -391,30 +441,85 @@ draw_boxes (state *st) } } -static void -handle_events (state *st) + +static unsigned long +boxfit_draw (Display *dpy, Window window, void *closure) { - XSync (st->dpy, False); - while (XPending (st->dpy)) + state *st = (state *) closure; + int delay; + + if (st->img_loader) /* still loading */ { - XEvent event; - XNextEvent (st->dpy, &event); - if (event.xany.type == ConfigureNotify || - event.xany.type == Expose) - reshape_boxes (st); - else if (event.xany.type == ButtonPress) - st->growing_p = !st->growing_p; - - screenhack_handle_event (st->dpy, &event); + st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0); + if (! st->img_loader) /* just finished */ + { + st->image = XGetImage (st->dpy, + (st->loading_pixmap ? st->loading_pixmap : + st->window), + 0, 0, + st->xgwa.width, st->xgwa.height, ~0L, + ZPixmap); + if (st->loading_pixmap) XFreePixmap (st->dpy, st->loading_pixmap); + XSetWindowBackground (st->dpy, st->window, st->bg_color); + if (st->loading_pixmap) + XClearWindow (st->dpy, st->window); + else + st->countdown = 2000000; + st->loading_pixmap = 0; + } + return st->delay; } + + if (st->countdown > 0) + { + st->countdown -= st->delay; + if (st->countdown <= 0) + { + st->countdown = 0; + XClearWindow (st->dpy, st->window); + } + return st->delay; + } + + if (st->growing_p) { + draw_boxes (st); + delay = grow_boxes (st); + } else { + delay = shrink_boxes (st); + draw_boxes (st); + } + return delay; } +static void +boxfit_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + state *st = (state *) closure; + reshape_boxes (st); +} - -char *progclass = "BoxFit"; +static Bool +boxfit_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + state *st = (state *) closure; + if (event->xany.type == ButtonPress) { + st->growing_p = !st->growing_p; + return True; + } + return False; +} -char *defaults [] = { +static void +boxfit_free (Display *dpy, Window window, void *closure) +{ +} + + +static const char *boxfit_defaults [] = { ".background: black", + ".foreground: #444444", + "*fpsSolid: true", "*delay: 20000", "*mode: random", "*colors: 64", @@ -422,38 +527,33 @@ char *defaults [] = { "*growBy: 1", "*spacing: 1", "*borderSize: 1", + "*grab: False", + "*peek: False", + "*grabDesktopImages: False", /* HAVE_COCOA */ + "*chooseRandomImages: True", /* HAVE_COCOA */ +#ifdef USE_IPHONE + "*ignoreRotation: True", +#endif 0 }; -XrmOptionDescRec options [] = { +static XrmOptionDescRec boxfit_options [] = { { "-delay", ".delay", XrmoptionSepArg, 0 }, { "-colors", ".colors", XrmoptionSepArg, 0 }, { "-count", ".boxCount", XrmoptionSepArg, 0 }, { "-growby", ".growBy", XrmoptionSepArg, 0 }, { "-spacing", ".spacing", XrmoptionSepArg, 0 }, { "-border", ".borderSize", XrmoptionSepArg, 0 }, + { "-mode", ".mode", XrmoptionSepArg, 0 }, { "-circles", ".mode", XrmoptionNoArg, "circles" }, { "-squares", ".mode", XrmoptionNoArg, "squares" }, { "-random", ".mode", XrmoptionNoArg, "random" }, + { "-grab", ".grab", XrmoptionNoArg, "True" }, + { "-no-grab", ".grab", XrmoptionNoArg, "False" }, + { "-peek", ".peek", XrmoptionNoArg, "True" }, + { "-no-peek", ".peek", XrmoptionNoArg, "False" }, { 0, 0, 0, 0 } }; -void -screenhack (Display *dpy, Window window) -{ - state *st = init_boxes (dpy, window); - int delay = get_integer_resource ("delay", "Integer"); - reshape_boxes (st); - while (1) - { - if (st->growing_p) - grow_boxes (st); - else - shrink_boxes (st); - - draw_boxes (st); - handle_events (st); - if (delay) usleep (delay); - } -} +XSCREENSAVER_MODULE ("BoxFit", boxfit)