/* wander, by Rick Campbell , 19 December 1998. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation. No representations are made about the suitability of this * software for any purpose. It is provided "as is" without express or * implied warranty. */ #include #include "screenhack.h" #include "colors.h" #include "erase.h" #define MAXIMUM_COLOR_COUNT (256) struct state { Display *dpy; Window window; unsigned int advance; Bool circles; Colormap color_map; int color_count; int color_index; XColor colors [MAXIMUM_COLOR_COUNT]; GC context; unsigned int density; int depth; int height; unsigned int length; unsigned int reset; Bool reset_p; unsigned int size; int width; int delay; int x, y, last_x, last_y, width_1, height_1, length_limit, reset_limit; unsigned long color; Pixmap pixmap; eraser_state *eraser; }; static void * wander_init (Display *dpy, Window window) { struct state *st = (struct state *) calloc (1, sizeof(*st)); XGCValues values; XWindowAttributes attributes; st->dpy = dpy; st->window = window; st->delay = get_integer_resource (st->dpy, "delay", "Integer"); XClearWindow (st->dpy, st->window); XGetWindowAttributes (st->dpy, st->window, &attributes); st->width = attributes.width; st->height = attributes.height; st->depth = attributes.depth; st->color_map = attributes.colormap; if (st->color_count) { free_colors (attributes.screen, st->color_map, st->colors, st->color_count); st->color_count = 0; } st->context = XCreateGC (st->dpy, st->window, 0, &values); st->color_count = MAXIMUM_COLOR_COUNT; make_color_loop (attributes.screen, attributes.visual, st->color_map, 0, 1, 1, 120, 1, 1, 240, 1, 1, st->colors, &st->color_count, True, False); if (st->color_count <= 0) { st->color_count = 2; st->colors [0].red = st->colors [0].green = st->colors [0].blue = 0; st->colors [1].red = st->colors [1].green = st->colors [1].blue = 0xFFFF; XAllocColor (st->dpy, st->color_map, &st->colors [0]); XAllocColor (st->dpy, st->color_map, &st->colors [1]); } st->color_index = NRAND (st->color_count); st->advance = get_integer_resource (st->dpy, "advance", "Integer"); st->density = get_integer_resource (st->dpy, "density", "Integer"); if (st->density < 1) st->density = 1; st->reset = get_integer_resource (st->dpy, "reset", "Integer"); if (st->reset < 100) st->reset = 100; st->circles = get_boolean_resource (st->dpy, "circles", "Boolean"); st->size = get_integer_resource (st->dpy, "size", "Integer"); if (st->size < 1) st->size = 1; st->width = st->width / st->size; st->height = st->height / st->size; st->length = get_integer_resource (st->dpy, "length", "Integer"); if (st->length < 1) st->length = 1; XSetForeground (st->dpy, st->context, st->colors [st->color_index].pixel); st->x = NRAND (st->width); st->y = NRAND (st->height); st->last_x = st->x; st->last_y = st->y; st->width_1 = st->width - 1; st->height_1 = st->height - 1; st->length_limit = st->length; st->reset_limit = st->reset; st->color_index = NRAND (st->color_count); st->color = st->colors [NRAND (st->color_count)].pixel; st->pixmap = XCreatePixmap (st->dpy, window, st->size, st->size, st->depth); XSetForeground (st->dpy, st->context, BlackPixel (st->dpy, DefaultScreen (st->dpy))); XFillRectangle (st->dpy, st->pixmap, st->context, 0, 0, st->width * st->size, st->height * st->size); XSetForeground (st->dpy, st->context, st->color); XFillArc (st->dpy, st->pixmap, st->context, 0, 0, st->size, st->size, 0, 360*64); return st; } static unsigned long wander_draw (Display *dpy, Window window, void *closure) { struct state *st = (struct state *) closure; int i; if (st->eraser) { st->eraser = erase_window (st->dpy, st->window, st->eraser); goto END; } for (i = 0; i < 2000; i++) { if (NRAND (st->density)) { st->x = st->last_x; st->y = st->last_y; } else { st->last_x = st->x; st->last_y = st->y; st->x += st->width_1 + NRAND (3); while (st->x >= st->width) st->x -= st->width; st->y += st->height_1 + NRAND (3); while (st->y >= st->height) st->y -= st->height; } if (NRAND (st->length_limit) == 0) { if (st->advance == 0) { st->color_index = NRAND (st->color_count); } else { st->color_index = (st->color_index + st->advance) % st->color_count; } st->color = st->colors [st->color_index].pixel; XSetForeground (st->dpy, st->context, st->color); if (st->circles) { XFillArc (st->dpy, st->pixmap, st->context, 0, 0, st->size, st->size, 0, 360 * 64); } } if (st->reset_p || NRAND (st->reset_limit) == 0) { st->reset_p = 0; st->eraser = erase_window (st->dpy, st->window, st->eraser); st->color = st->colors [NRAND (st->color_count)].pixel; st->x = NRAND (st->width); st->y = NRAND (st->height); st->last_x = st->x; st->last_y = st->y; if (st->circles) { XFillArc (st->dpy, st->pixmap, st->context, 0, 0, st->size, st->size, 0, 360*64); } } if (st->size == 1) { XDrawPoint (st->dpy, st->window, st->context, st->x, st->y); } else { if (st->circles) { XCopyArea (st->dpy, st->pixmap, st->window, st->context, 0, 0, st->size, st->size, st->x * st->size, st->y * st->size); } else { XFillRectangle (st->dpy, st->window, st->context, st->x * st->size, st->y * st->size, st->size, st->size); } } } END: return st->delay; } static void wander_reshape (Display *dpy, Window window, void *closure, unsigned int w, unsigned int h) { struct state *st = (struct state *) closure; st->width = w / st->size; st->height = h / st->size; st->width_1 = st->width - 1; st->height_1 = st->height - 1; } static Bool wander_event (Display *dpy, Window window, void *closure, XEvent *event) { struct state *st = (struct state *) closure; if (screenhack_event_helper (dpy, window, event)) { st->reset_p = 1; return True; } return False; } static void wander_free (Display *dpy, Window window, void *closure) { struct state *st = (struct state *) closure; XFreeGC (st->dpy, st->context); if (st->eraser) eraser_free (st->eraser); free (st); } static const char *wander_defaults [] = { ".lowrez: true", ".background: black", ".foreground: white", ".fpsSolid: true", ".advance: 1", ".density: 2", ".length: 25000", ".delay: 20000", ".reset: 2500000", ".circles: False", ".size: 1", #ifdef HAVE_MOBILE "*ignoreRotation: True", #endif 0 }; static XrmOptionDescRec wander_options [] = { { "-advance", ".advance", XrmoptionSepArg, 0 }, { "-circles", ".circles", XrmoptionNoArg, "True" }, { "-no-circles",".circles", XrmoptionNoArg, "False" }, { "-density", ".density", XrmoptionSepArg, 0 }, { "-length", ".length", XrmoptionSepArg, 0 }, { "-delay", ".delay", XrmoptionSepArg, 0 }, { "-reset", ".reset", XrmoptionSepArg, 0 }, { "-size", ".size", XrmoptionSepArg, 0 }, { 0, 0, 0, 0 } }; XSCREENSAVER_MODULE ("Wander", wander)