1 /* rotzoomer - creates a collage of rotated and scaled portions of the screen
2 * Copyright (C) 2001 Claudio Matsuoka <claudio@helllabs.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
16 * -shm enable MIT shared memory extension
17 * -no-shm disable MIT shared memory extension
18 * -n <num> number of zoomboxes
19 * -move enable mobile zoomboxes
20 * -sweep enable sweep mode
21 * -anim enable snapshot mode
22 * -no-anim enable snapshot mode
23 * -delay delay in milliseconds
27 #include "screenhack.h"
28 #include <X11/Xutil.h>
30 #ifdef HAVE_XSHM_EXTENSION
33 static XShmSegmentInfo shm_info;
37 int w, h; /* rectangle width and height */
38 int inc1, inc2; /* rotation and zoom angle increments */
39 int dx, dy; /* translation increments */
40 int a1, a2; /* rotation and zoom angular variables */
41 int ox, oy; /* origin in the background copy */
42 int xx, yy; /* left-upper corner position (* 256) */
43 int x, y; /* left-upper corner position */
44 int ww, hh; /* valid area to place left-upper corner */
45 int n; /* number of iteractions */
46 int count; /* current iteraction */
50 static Display *display;
52 static Visual *visual;
53 static XImage *orig_map, *buffer_map;
54 static Colormap colormap;
56 static int width, height;
57 static struct zoom_area **zoom_box;
58 static int num_zoom = 2;
61 static int delay = 10;
65 static void rotzoom (struct zoom_area *za)
67 int x, y, c, s, zoom, z;
68 int x2 = za->x + za->w - 1, y2 = za->y + za->h - 1;
71 z = 8100 * sin (M_PI * za->a2 / 8192);
74 c = zoom * cos (M_PI * za->a1 / 8192);
75 s = zoom * sin (M_PI * za->a1 / 8192);
76 for (y = za->y; y <= y2; y++) {
77 for (x = za->x; x <= x2; x++) {
78 ox = (x * c + y * s) >> 13;
79 oy = (-x * s + y * c) >> 13;
90 XPutPixel (buffer_map, x, y, XGetPixel (orig_map, ox, oy));
94 za->a1 += za->inc1; /* Rotation angle */
97 za->a2 += za->inc2; /* Zoom */
100 za->ox = ox; /* Save state for next iteration */
107 static void reset_zoom (struct zoom_area *za)
110 int speed = random () % 100 + 100;
111 switch (random () % 4) {
119 za->n = (height - 10) * 256 / speed;
128 za->n = (width - 10) * 256 / speed;
137 za->n = (height - 10) * 256 / speed;
146 za->n = (width - 10) * 256 / speed;
149 za->ww = width - za->w;
150 za->hh = height - za->h;
152 /* We want smaller angle increments in sweep mode (looks better) */
156 za->inc1 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
157 za->inc2 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
159 za->w = 50 + random() % 300;
160 za->h = 50 + random() % 300;
162 if (za->w > width / 3)
164 if (za->h > height / 3)
167 za->ww = width - za->w;
168 za->hh = height - za->h;
170 za->x = (random() % za->ww);
171 za->y = (random() % za->hh);
173 za->dx = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
174 za->dy = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
177 za->n = 50 + random() % 1000;
181 za->n = 5 + random() % 10;
186 za->inc1 = ((2 * (random() & 1)) - 1) * (random () % 30);
187 za->inc2 = ((2 * (random() & 1)) - 1) * (random () % 30);
190 za->xx = za->x * 256;
191 za->yy = za->y * 256;
197 static struct zoom_area *create_zoom (void)
199 struct zoom_area *za;
201 za = malloc (sizeof (struct zoom_area));
208 static void update_position (struct zoom_area *za)
218 za->dx = 100 + random() % 100;
223 za->dy = 100 + random() % 100;
226 if (za->x > za->ww) {
228 za->dx = -(100 + random() % 100);
231 if (za->y > za->hh) {
233 za->dy = -(100 + random() % 100);
238 static void DisplayImage (int x, int y, int w, int h)
240 #ifdef HAVE_XSHM_EXTENSION
242 XShmPutImage (display, window, gc, buffer_map, x, y, x, y,
245 #endif /* HAVE_XSHM_EXTENSION */
246 XPutImage(display, window, gc, buffer_map, x, y, x, y, w, h);
250 static void hack_main (void)
254 for (i = 0; i < num_zoom; i++) {
256 update_position (zoom_box[i]);
258 if (zoom_box[i]->n > 0) {
259 if (anim || zoom_box[i]->count == 0) {
260 rotzoom (zoom_box[i]);
266 reset_zoom (zoom_box[i]);
270 for (i = 0; i < num_zoom; i++) {
271 DisplayImage(zoom_box[i]->x, zoom_box[i]->y,
272 zoom_box[i]->w, zoom_box[i]->h);
275 XSync(display,False);
276 screenhack_handle_events(display);
280 static void init_hack (void)
284 zoom_box = calloc (num_zoom, sizeof (struct zoom_area *));
285 for (i = 0; i < num_zoom; i++) {
286 zoom_box[i] = create_zoom ();
289 memcpy (buffer_map->data, orig_map->data,
290 height * buffer_map->bytes_per_line);
292 DisplayImage(0, 0, width, height);
293 XSync(display,False);
297 static void setup_X (Display * disp, Window win)
299 XWindowAttributes xwa;
304 XGetWindowAttributes (disp, win, &xwa);
308 colormap = xwa.colormap;
318 gcv.function = GXcopy;
319 gcv.subwindow_mode = IncludeInferiors;
320 gcflags = GCForeground | GCFunction;
321 if (use_subwindow_mode_p (xwa.screen, window)) /* see grabscreen.c */
322 gcflags |= GCSubwindowMode;
323 gc = XCreateGC (display, window, gcflags, &gcv);
324 load_random_image (xwa.screen, window, window, NULL);
326 orig_map = XGetImage (display, window, 0, 0, width, height, ~0L, ZPixmap);
329 fprintf(stderr, "XCreateGC failed\n");
335 #ifdef HAVE_XSHM_EXTENSION
337 buffer_map = create_xshm_image(display, xwa.visual, depth,
338 ZPixmap, 0, &shm_info, width, height);
341 fprintf(stderr, "create_xshm_image failed\n");
344 #endif /* HAVE_XSHM_EXTENSION */
347 buffer_map = XCreateImage(display, xwa.visual,
348 depth, ZPixmap, 0, 0, width, height, 8, 0);
349 buffer_map->data = (char *)calloc (buffer_map->height,
350 buffer_map->bytes_per_line);
355 char *progclass = "Rotzoomer";
358 #ifdef HAVE_XSHM_EXTENSION
370 XrmOptionDescRec options[] = {
371 #ifdef HAVE_XSHM_EXTENSION
372 { "-shm", ".useSHM", XrmoptionNoArg, "True" },
373 { "-no-shm", ".useSHM", XrmoptionNoArg, "False" },
375 { "-move", ".move", XrmoptionNoArg, "True" },
376 { "-sweep", ".sweep", XrmoptionNoArg, "True" },
377 { "-anim", ".anim", XrmoptionNoArg, "True" },
378 { "-no-anim", ".anim", XrmoptionNoArg, "False" },
379 { "-delay", ".delay", XrmoptionSepArg, 0 },
380 { "-n", ".numboxes", XrmoptionSepArg, 0 },
385 void screenhack(Display *disp, Window win)
387 #ifdef HAVE_XSHM_EXTENSION
388 use_shm = get_boolean_resource ("useSHM", "Boolean");
390 num_zoom = get_integer_resource ("numboxes", "Integer");
391 move = get_boolean_resource ("move", "Boolean");
392 delay = get_integer_resource ("delay", "Integer");
393 sweep = get_boolean_resource ("sweep", "Boolean");
394 anim = get_boolean_resource ("anim", "Boolean");
396 /* In sweep or static mode, we want only one box */
400 /* Can't have static sweep mode */
408 /* Main drawing loop */
411 usleep (delay * 1000);