~ubuntu-branches/ubuntu/lucid/xscreensaver/lucid

« back to all changes in this revision

Viewing changes to hacks/rotzoomer.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2007-12-06 09:53:12 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20071206095312-fkzcwe4vqm50z208
Tags: 5.04-1ubuntu1
* Merge from debian unstable, remaining changes:
  - split xscreensaver into xscreensaver, xscreensaver-data (hacks we ship),
    xscreensaver-data-extra (hacks in universe). split out gl hacks for
    universe to xscreensaver-gl-extra
  - use fridge for rss screensavers
  - create and install .desktop files for gnome-screensaver

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
 
26
26
#include <math.h>
27
27
#include "screenhack.h"
28
 
#include <X11/Xutil.h>
29
28
 
30
29
#ifdef HAVE_XSHM_EXTENSION
31
30
#include "xshm.h"
32
 
static Bool use_shm;
33
 
static XShmSegmentInfo shm_info;
34
31
#endif
35
32
 
36
33
struct zoom_area {
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 */
47
 
};
48
 
 
49
 
static Window window;
50
 
static Display *display;
51
 
static GC gc;
52
 
static Visual *visual;
53
 
static XImage *orig_map, *buffer_map;
54
 
static Colormap colormap;
55
 
 
56
 
static int width, height;
57
 
static struct zoom_area **zoom_box;
58
 
static int num_zoom = 2;
59
 
static int move = 0;
60
 
static int sweep = 0;
61
 
static int delay = 10;
62
 
static int anim = 1;
63
 
 
64
 
 
65
 
static void rotzoom (struct zoom_area *za)
66
 
{
67
 
        int x, y, c, s, zoom, z;
68
 
        int x2 = za->x + za->w - 1, y2 = za->y + za->h - 1;
69
 
        int ox = 0, oy = 0;
70
 
 
71
 
        z = 8100 * sin (M_PI * za->a2 / 8192);
72
 
        zoom = 8192 + z;
73
 
 
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;
80
 
 
81
 
                        while (ox < 0)
82
 
                                ox += width;
83
 
                        while (oy < 0)
84
 
                                oy += height;
85
 
                        while (ox >= width)
86
 
                                ox -= width;
87
 
                        while (oy >= height)
88
 
                                oy -= height;
89
 
 
90
 
                        XPutPixel (buffer_map, x, y, XGetPixel (orig_map, ox, oy));
91
 
                }
92
 
        }
93
 
 
94
 
        za->a1 += za->inc1;             /* Rotation angle */
95
 
        za->a1 &= 0x3fff;;
96
 
 
97
 
        za->a2 += za->inc2;             /* Zoom */
98
 
        za->a2 &= 0x3fff;
99
 
 
100
 
        za->ox = ox;                    /* Save state for next iteration */
101
 
        za->oy = oy;
102
 
 
103
 
        za->count++;
104
 
}
105
 
 
106
 
 
107
 
static void reset_zoom (struct zoom_area *za)
108
 
{
109
 
        if (sweep) {
110
 
                int speed = random () % 100 + 100;
111
 
                switch (random () % 4) {
112
 
                case 0:
113
 
                        za->w = width;
114
 
                        za->h = 10;
115
 
                        za->x = 0;
116
 
                        za->y = 0;
117
 
                        za->dx = 0;
118
 
                        za->dy = speed;
119
 
                        za->n = (height - 10) * 256 / speed;
120
 
                        break;
121
 
                case 1:
122
 
                        za->w = 10;
123
 
                        za->h = height;
124
 
                        za->x = width - 10;
125
 
                        za->y = 0;
126
 
                        za->dx = -speed;
127
 
                        za->dy = 0;
128
 
                        za->n = (width - 10) * 256 / speed;
129
 
                        break;
130
 
                case 2:
131
 
                        za->w = width;
132
 
                        za->h = 10;
133
 
                        za->x = 0;
134
 
                        za->y = height - 10;
135
 
                        za->dx = 0;
136
 
                        za->dy = -speed;
137
 
                        za->n = (height - 10) * 256 / speed;
138
 
                        break;
139
 
                case 3:
140
 
                        za->w = 10;
141
 
                        za->h = height;
142
 
                        za->x = 0;
143
 
                        za->y = 0;
144
 
                        za->dx = speed;
145
 
                        za->dy = 0;
146
 
                        za->n = (width - 10) * 256 / speed;
147
 
                        break;
148
 
                }
149
 
                za->ww = width - za->w;
150
 
                za->hh = height - za->h;
151
 
 
152
 
                /* We want smaller angle increments in sweep mode (looks better) */
153
 
 
154
 
                za->a1 = 0;
155
 
                za->a2 = 0;
156
 
                za->inc1 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
157
 
                za->inc2 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
158
 
        } else {
159
 
                za->w = 50 + random() % 300;
160
 
                za->h = 50 + random() % 300;
161
 
 
162
 
                if (za->w > width / 3)
163
 
                        za->w = width / 3;
164
 
                if (za->h > height / 3)
165
 
                        za->h = height / 3;
166
 
 
167
 
                za->ww = width - za->w;
168
 
                za->hh = height - za->h;
169
 
 
170
 
                za->x = (random() % za->ww);
171
 
                za->y = (random() % za->hh);
172
 
 
173
 
                za->dx = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
174
 
                za->dy = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
175
 
 
176
 
                if (anim) {
177
 
                        za->n = 50 + random() % 1000;
178
 
                        za->a1 = 0;
179
 
                        za->a2 = 0;
180
 
                } else {
181
 
                        za->n = 5 + random() % 10;
182
 
                        za->a1 = random ();
183
 
                        za->a2 = random ();
184
 
                }
185
 
 
186
 
                za->inc1 = ((2 * (random() & 1)) - 1) * (random () % 30);
187
 
                za->inc2 = ((2 * (random() & 1)) - 1) * (random () % 30);
188
 
        }
189
 
 
190
 
        za->xx = za->x * 256;
191
 
        za->yy = za->y * 256;
192
 
 
193
 
        za->count = 0;
194
 
}
195
 
 
196
 
 
197
 
static struct zoom_area *create_zoom (void)
198
 
{
199
 
        struct zoom_area *za;
200
 
 
201
 
        za = malloc (sizeof (struct zoom_area));
202
 
        reset_zoom (za);
203
 
 
204
 
        return za;
205
 
}
206
 
 
207
 
 
208
 
static void update_position (struct zoom_area *za)
209
 
{
210
 
        za->xx += za->dx;
211
 
        za->yy += za->dy;
212
 
 
213
 
        za->x = za->xx >> 8;
214
 
        za->y = za->yy >> 8;
215
 
 
216
 
        if (za->x < 0) {
217
 
                za->x = 0;
218
 
                za->dx = 100 + random() % 100;
219
 
        }
220
 
                
221
 
        if (za->y < 0) {
222
 
                za->y = 0;
223
 
                za->dy = 100 + random() % 100;
224
 
        }
225
 
                
226
 
        if (za->x > za->ww) {
227
 
                za->x = za->ww;
228
 
                za->dx = -(100 + random() % 100);
229
 
        }
230
 
 
231
 
        if (za->y > za->hh) {
232
 
                za->y = za->hh;
233
 
                za->dy = -(100 + random() % 100);
234
 
        }
235
 
}
236
 
 
237
 
 
238
 
static void DisplayImage (int x, int y, int w, int h)
239
 
{
240
 
#ifdef HAVE_XSHM_EXTENSION
241
 
        if (use_shm)
242
 
                XShmPutImage (display, window, gc, buffer_map, x, y, x, y,
243
 
                        w, h, False);
244
 
        else
245
 
#endif /* HAVE_XSHM_EXTENSION */
246
 
                XPutImage(display, window, gc, buffer_map, x, y, x, y, w, h);
247
 
}
248
 
 
249
 
 
250
 
static void hack_main (void)
251
 
{
252
 
        int i;
253
 
 
254
 
        for (i = 0; i < num_zoom; i++) {
255
 
                if (move || sweep)
256
 
                        update_position (zoom_box[i]);
257
 
 
258
 
                if (zoom_box[i]->n > 0) {
259
 
                        if (anim || zoom_box[i]->count == 0) {
260
 
                                rotzoom (zoom_box[i]);
261
 
                        } else {
262
 
                                sleep (1);
263
 
                        }
264
 
                        zoom_box[i]->n--;
265
 
                } else {
266
 
                        reset_zoom (zoom_box[i]);
267
 
                }
268
 
        }
269
 
 
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);
273
 
        }
274
 
 
275
 
        XSync(display,False);
276
 
        screenhack_handle_events(display);
277
 
}
278
 
 
279
 
 
280
 
static void init_hack (void)
281
 
{
282
 
        int i;
283
 
 
284
 
        zoom_box = calloc (num_zoom, sizeof (struct zoom_area *));
285
 
        for (i = 0; i < num_zoom; i++) {
286
 
                zoom_box[i] = create_zoom ();
287
 
        }
288
 
 
289
 
        memcpy (buffer_map->data, orig_map->data,
290
 
                height * buffer_map->bytes_per_line);
291
 
 
292
 
        DisplayImage(0, 0, width, height);
293
 
        XSync(display,False);
294
 
}
295
 
 
296
 
 
297
 
static void setup_X (Display * disp, Window win)
298
 
{
299
 
        XWindowAttributes xwa;
300
 
        int depth;
301
 
        XGCValues gcv;
302
 
        long gcflags;
303
 
 
304
 
        XGetWindowAttributes (disp, win, &xwa);
305
 
        window = win;
306
 
        display = disp;
307
 
        depth = xwa.depth;
308
 
        colormap = xwa.colormap;
309
 
        width = xwa.width;
310
 
        height = xwa.height;
311
 
        visual = xwa.visual;
312
 
 
313
 
        if (width % 2)
314
 
                width--;
315
 
        if (height % 2)
316
 
                height--;
317
 
 
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, NULL);
325
 
 
326
 
        orig_map = XGetImage (display, window, 0, 0, width, height, ~0L, ZPixmap);
327
 
 
328
 
        if (!gc) {
329
 
                fprintf(stderr, "XCreateGC failed\n");
330
 
                exit(1);
331
 
        }
332
 
 
333
 
        buffer_map = 0;
334
 
 
335
 
#ifdef HAVE_XSHM_EXTENSION
336
 
        if (use_shm) {
337
 
                buffer_map = create_xshm_image(display, xwa.visual, depth,
338
 
                        ZPixmap, 0, &shm_info, width, height);
339
 
                if (!buffer_map) {
340
 
                        use_shm = False;
341
 
                        fprintf(stderr, "create_xshm_image failed\n");
342
 
                }
343
 
        }
344
 
#endif /* HAVE_XSHM_EXTENSION */
345
 
 
346
 
        if (!buffer_map) {
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);
351
 
        }
352
 
}
353
 
 
354
 
 
355
 
char *progclass = "Rotzoomer";
356
 
 
357
 
char *defaults[] = {
358
 
#ifdef HAVE_XSHM_EXTENSION
359
 
        "*useSHM: True",
360
 
#endif
361
 
        "*move: False",
362
 
        "*sweep: False",
363
 
        "*anim: True",
364
 
        "*numboxes: 2",
365
 
        "*delay: 10",
366
 
        0
367
 
};
368
 
 
369
 
 
370
 
XrmOptionDescRec options[] = {
371
 
#ifdef HAVE_XSHM_EXTENSION
372
 
        { "-shm",       ".useSHM",      XrmoptionNoArg, "True"  },
373
 
        { "-no-shm",    ".useSHM",      XrmoptionNoArg, "False" },
374
 
#endif
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      },
381
 
        { 0, 0, 0, 0 }
382
 
};
383
 
 
384
 
 
385
 
void screenhack(Display *disp, Window win)
386
 
{
387
 
#ifdef HAVE_XSHM_EXTENSION
388
 
        use_shm = get_boolean_resource ("useSHM", "Boolean");
389
 
#endif
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");
395
 
 
396
 
        /* In sweep or static mode, we want only one box */
397
 
        if (sweep || !anim)
398
 
                num_zoom = 1;
399
 
 
400
 
        /* Can't have static sweep mode */
401
 
        if (!anim)
402
 
                sweep = 0;
403
 
 
404
 
        setup_X (disp, win);
405
 
 
406
 
        init_hack ();
407
 
 
408
 
        /* Main drawing loop */
409
 
        while (42) {
410
 
                hack_main ();
411
 
                usleep (delay * 1000);
412
 
        }
413
 
}
 
34
  int w, h;             /* rectangle width and height */
 
35
  int inc1, inc2;       /* rotation and zoom angle increments */
 
36
  int dx, dy;           /* translation increments */
 
37
  int a1, a2;           /* rotation and zoom angular variables */
 
38
  int ox, oy;           /* origin in the background copy */
 
39
  int xx, yy;           /* left-upper corner position (* 256) */
 
40
  int x, y;             /* left-upper corner position */
 
41
  int ww, hh;           /* valid area to place left-upper corner */
 
42
  int n;                /* number of iteractions */
 
43
  int count;            /* current iteraction */
 
44
};
 
45
 
 
46
struct state {
 
47
  Display *dpy;
 
48
  Window window;
 
49
 
 
50
  GC gc;
 
51
  Visual *visual;
 
52
  XImage *orig_map, *buffer_map;
 
53
  Colormap colormap;
 
54
 
 
55
  int width, height;
 
56
  struct zoom_area **zoom_box;
 
57
  int num_zoom;
 
58
  int move;
 
59
  int sweep;
 
60
  int delay;
 
61
  int anim;
 
62
 
 
63
  async_load_state *img_loader;
 
64
 
 
65
#ifdef HAVE_XSHM_EXTENSION
 
66
  Bool use_shm;
 
67
  XShmSegmentInfo shm_info;
 
68
#endif
 
69
};
 
70
 
 
71
 
 
72
static void
 
73
rotzoom (struct state *st, struct zoom_area *za)
 
74
{
 
75
  int x, y, c, s, zoom, z;
 
76
  int x2 = za->x + za->w - 1, y2 = za->y + za->h - 1;
 
77
  int ox = 0, oy = 0;
 
78
 
 
79
  z = 8100 * sin (M_PI * za->a2 / 8192);
 
80
  zoom = 8192 + z;
 
81
 
 
82
  c = zoom * cos (M_PI * za->a1 / 8192);
 
83
  s = zoom * sin (M_PI * za->a1 / 8192);
 
84
  for (y = za->y; y <= y2; y++) {
 
85
    for (x = za->x; x <= x2; x++) {
 
86
      ox = (x * c + y * s) >> 13;
 
87
      oy = (-x * s + y * c) >> 13;
 
88
 
 
89
      while (ox < 0)
 
90
        ox += st->width;
 
91
      while (oy < 0)
 
92
        oy += st->height;
 
93
      while (ox >= st->width)
 
94
        ox -= st->width;
 
95
      while (oy >= st->height)
 
96
        oy -= st->height;
 
97
 
 
98
      XPutPixel (st->buffer_map, x, y, XGetPixel (st->orig_map, ox, oy));
 
99
    }
 
100
  }
 
101
 
 
102
  za->a1 += za->inc1;           /* Rotation angle */
 
103
  za->a1 &= 0x3fff;;
 
104
 
 
105
  za->a2 += za->inc2;           /* Zoom */
 
106
  za->a2 &= 0x3fff;
 
107
 
 
108
  za->ox = ox;                  /* Save state for next iteration */
 
109
  za->oy = oy;
 
110
 
 
111
  za->count++;
 
112
}
 
113
 
 
114
 
 
115
static void
 
116
reset_zoom (struct state *st, struct zoom_area *za)
 
117
{
 
118
  if (st->sweep) {
 
119
    int speed = random () % 100 + 100;
 
120
    switch (random () % 4) {
 
121
    case 0:
 
122
      za->w = st->width;
 
123
      za->h = 10;
 
124
      za->x = 0;
 
125
      za->y = 0;
 
126
      za->dx = 0;
 
127
      za->dy = speed;
 
128
      za->n = (st->height - 10) * 256 / speed;
 
129
      break;
 
130
    case 1:
 
131
      za->w = 10;
 
132
      za->h = st->height;
 
133
      za->x = st->width - 10;
 
134
      za->y = 0;
 
135
      za->dx = -speed;
 
136
      za->dy = 0;
 
137
      za->n = (st->width - 10) * 256 / speed;
 
138
      break;
 
139
    case 2:
 
140
      za->w = st->width;
 
141
      za->h = 10;
 
142
      za->x = 0;
 
143
      za->y = st->height - 10;
 
144
      za->dx = 0;
 
145
      za->dy = -speed;
 
146
      za->n = (st->height - 10) * 256 / speed;
 
147
      break;
 
148
    case 3:
 
149
      za->w = 10;
 
150
      za->h = st->height;
 
151
      za->x = 0;
 
152
      za->y = 0;
 
153
      za->dx = speed;
 
154
      za->dy = 0;
 
155
      za->n = (st->width - 10) * 256 / speed;
 
156
      break;
 
157
    }
 
158
    za->ww = st->width - za->w;
 
159
    za->hh = st->height - za->h;
 
160
 
 
161
    /* We want smaller angle increments in sweep mode (looks better) */
 
162
 
 
163
    za->a1 = 0;
 
164
    za->a2 = 0;
 
165
    za->inc1 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
 
166
    za->inc2 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
 
167
  } else {
 
168
    za->w = 50 + random() % 300;
 
169
    za->h = 50 + random() % 300;
 
170
 
 
171
    if (za->w > st->width / 3)
 
172
      za->w = st->width / 3;
 
173
    if (za->h > st->height / 3)
 
174
      za->h = st->height / 3;
 
175
 
 
176
    za->ww = st->width - za->w;
 
177
    za->hh = st->height - za->h;
 
178
 
 
179
    za->x = (za->ww ? random() % za->ww : 0);
 
180
    za->y = (za->hh ? random() % za->hh : 0);
 
181
 
 
182
    za->dx = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
 
183
    za->dy = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
 
184
 
 
185
    if (st->anim) {
 
186
      za->n = 50 + random() % 1000;
 
187
      za->a1 = 0;
 
188
      za->a2 = 0;
 
189
    } else {
 
190
      za->n = 5 + random() % 10;
 
191
      za->a1 = random ();
 
192
      za->a2 = random ();
 
193
    }
 
194
 
 
195
    za->inc1 = ((2 * (random() & 1)) - 1) * (random () % 30);
 
196
    za->inc2 = ((2 * (random() & 1)) - 1) * (random () % 30);
 
197
  }
 
198
 
 
199
  za->xx = za->x * 256;
 
200
  za->yy = za->y * 256;
 
201
 
 
202
  za->count = 0;
 
203
}
 
204
 
 
205
 
 
206
static struct zoom_area *
 
207
create_zoom (struct state *st)
 
208
{
 
209
  struct zoom_area *za;
 
210
 
 
211
  za = malloc (sizeof (struct zoom_area));
 
212
  reset_zoom (st, za);
 
213
 
 
214
  return za;
 
215
}
 
216
 
 
217
 
 
218
static void
 
219
update_position (struct zoom_area *za)
 
220
{
 
221
  za->xx += za->dx;
 
222
  za->yy += za->dy;
 
223
 
 
224
  za->x = za->xx >> 8;
 
225
  za->y = za->yy >> 8;
 
226
 
 
227
  if (za->x < 0) {
 
228
    za->x = 0;
 
229
    za->dx = 100 + random() % 100;
 
230
  }
 
231
                
 
232
  if (za->y < 0) {
 
233
    za->y = 0;
 
234
    za->dy = 100 + random() % 100;
 
235
  }
 
236
                
 
237
  if (za->x > za->ww) {
 
238
    za->x = za->ww;
 
239
    za->dx = -(100 + random() % 100);
 
240
  }
 
241
 
 
242
  if (za->y > za->hh) {
 
243
    za->y = za->hh;
 
244
    za->dy = -(100 + random() % 100);
 
245
  }
 
246
}
 
247
 
 
248
 
 
249
static void
 
250
DisplayImage (struct state *st, int x, int y, int w, int h)
 
251
{
 
252
#ifdef HAVE_XSHM_EXTENSION
 
253
  if (st->use_shm)
 
254
    XShmPutImage (st->dpy, st->window, st->gc, st->buffer_map, x, y, x, y,
 
255
                  w, h, False);
 
256
  else
 
257
#endif /* HAVE_XSHM_EXTENSION */
 
258
    XPutImage(st->dpy, st->window, st->gc, st->buffer_map, x, y, x, y, w, h);
 
259
}
 
260
 
 
261
 
 
262
static void
 
263
init_hack (struct state *st)
 
264
{
 
265
  int i;
 
266
 
 
267
  st->zoom_box = calloc (st->num_zoom, sizeof (struct zoom_area *));
 
268
  for (i = 0; i < st->num_zoom; i++) {
 
269
    st->zoom_box[i] = create_zoom (st);
 
270
  }
 
271
 
 
272
  if (st->height && st->orig_map->data)
 
273
    memcpy (st->buffer_map->data, st->orig_map->data,
 
274
            st->height * st->buffer_map->bytes_per_line);
 
275
 
 
276
  DisplayImage(st, 0, 0, st->width, st->height);
 
277
}
 
278
 
 
279
 
 
280
static unsigned long
 
281
rotzoomer_draw (Display *disp, Window win, void *closure)
 
282
{
 
283
  struct state *st = (struct state *) closure;
 
284
  int delay = (st->delay * 1000);
 
285
  int i;
 
286
 
 
287
  if (st->img_loader)   /* still loading */
 
288
    {
 
289
      st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0);
 
290
      if (! st->img_loader) {  /* just finished */
 
291
        st->orig_map = XGetImage (st->dpy, st->window, 0, 0, 
 
292
                                  st->width, st->height, ~0L, ZPixmap);
 
293
        init_hack (st);
 
294
      }
 
295
      return st->delay;
 
296
    }
 
297
 
 
298
  for (i = 0; i < st->num_zoom; i++) {
 
299
    if (st->move || st->sweep)
 
300
      update_position (st->zoom_box[i]);
 
301
 
 
302
    if (st->zoom_box[i]->n > 0) {
 
303
      if (st->anim || st->zoom_box[i]->count == 0) {
 
304
        rotzoom (st, st->zoom_box[i]);
 
305
      } else {
 
306
        delay = 1000000;
 
307
      }
 
308
      st->zoom_box[i]->n--;
 
309
    } else {
 
310
      reset_zoom (st, st->zoom_box[i]);
 
311
    }
 
312
  }
 
313
 
 
314
  for (i = 0; i < st->num_zoom; i++) {
 
315
    DisplayImage(st, st->zoom_box[i]->x, st->zoom_box[i]->y,
 
316
                 st->zoom_box[i]->w, st->zoom_box[i]->h);
 
317
  }
 
318
 
 
319
  return delay;
 
320
}
 
321
 
 
322
 
 
323
static void
 
324
setup_X (struct state *st)
 
325
{
 
326
  XWindowAttributes xgwa;
 
327
  int depth;
 
328
  XGCValues gcv;
 
329
  long gcflags;
 
330
 
 
331
  XGetWindowAttributes (st->dpy, st->window, &xgwa);
 
332
  depth = xgwa.depth;
 
333
  st->colormap = xgwa.colormap;
 
334
  st->width = xgwa.width;
 
335
  st->height = xgwa.height;
 
336
  st->visual = xgwa.visual;
 
337
 
 
338
  if (st->width % 2)
 
339
    st->width--;
 
340
  if (st->height % 2)
 
341
    st->height--;
 
342
 
 
343
  gcv.function = GXcopy;
 
344
  gcv.subwindow_mode = IncludeInferiors;
 
345
  gcflags = GCFunction;
 
346
  if (use_subwindow_mode_p (xgwa.screen, st->window))   /* see grabscreen.c */
 
347
    gcflags |= GCSubwindowMode;
 
348
  st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv);
 
349
  st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
 
350
                                            st->window, 0, 0);
 
351
 
 
352
  st->buffer_map = 0;
 
353
 
 
354
#ifdef HAVE_XSHM_EXTENSION
 
355
  if (st->use_shm) {
 
356
    st->buffer_map = create_xshm_image(st->dpy, xgwa.visual, depth,
 
357
                                       ZPixmap, 0, &st->shm_info, st->width, st->height);
 
358
    if (!st->buffer_map) {
 
359
      st->use_shm = False;
 
360
      fprintf(stderr, "create_xshm_image failed\n");
 
361
    }
 
362
  }
 
363
#endif /* HAVE_XSHM_EXTENSION */
 
364
 
 
365
  if (!st->buffer_map) {
 
366
    st->buffer_map = XCreateImage(st->dpy, xgwa.visual,
 
367
                                  depth, ZPixmap, 0, 0, st->width, st->height, 8, 0);
 
368
    st->buffer_map->data = (char *)calloc (st->buffer_map->height,
 
369
                                           st->buffer_map->bytes_per_line);
 
370
  }
 
371
}
 
372
 
 
373
 
 
374
static void *
 
375
rotzoomer_init (Display *dpy, Window window)
 
376
{
 
377
  struct state *st = (struct state *) calloc (1, sizeof(*st));
 
378
  char *s;
 
379
  st->dpy = dpy;
 
380
  st->window = window;
 
381
#ifdef HAVE_XSHM_EXTENSION
 
382
  st->use_shm = get_boolean_resource (st->dpy, "useSHM", "Boolean");
 
383
#endif
 
384
  st->num_zoom = get_integer_resource (st->dpy, "numboxes", "Integer");
 
385
 
 
386
  s = get_string_resource (dpy, "mode", "Mode");
 
387
  if (!s || !*s || !strcasecmp (s, "stationary"))
 
388
    ;
 
389
  else if (!strcasecmp (s, "move"))
 
390
    st->move = True;
 
391
  else if (!strcasecmp (s, "sweep"))
 
392
    st->sweep = True;
 
393
  else
 
394
    fprintf (stderr, "%s: bogus mode: \"%s\"\n", progname, s);
 
395
 
 
396
  st->anim = get_boolean_resource (st->dpy, "anim", "Boolean");
 
397
  st->delay = get_integer_resource (st->dpy, "delay", "Integer");
 
398
 
 
399
  /* In sweep or static mode, we want only one box */
 
400
  if (st->sweep || !st->anim)
 
401
    st->num_zoom = 1;
 
402
 
 
403
  /* Can't have static sweep mode */
 
404
  if (!st->anim)
 
405
    st->sweep = 0;
 
406
 
 
407
  setup_X (st);
 
408
 
 
409
  return st;
 
410
}
 
411
 
 
412
static void
 
413
rotzoomer_reshape (Display *dpy, Window window, void *closure, 
 
414
                 unsigned int w, unsigned int h)
 
415
{
 
416
}
 
417
 
 
418
static Bool
 
419
rotzoomer_event (Display *dpy, Window window, void *closure, XEvent *event)
 
420
{
 
421
  return False;
 
422
}
 
423
 
 
424
static void
 
425
rotzoomer_free (Display *dpy, Window window, void *closure)
 
426
{
 
427
  struct state *st = (struct state *) closure;
 
428
  free (st);
 
429
}
 
430
 
 
431
 
 
432
static const char *rotzoomer_defaults[] = {
 
433
  ".background: black",
 
434
  ".foreground: white",
 
435
#ifdef HAVE_XSHM_EXTENSION
 
436
  "*useSHM: True",
 
437
#else
 
438
  "*useSHM: False",
 
439
#endif
 
440
  "*anim: True",
 
441
  "*mode: stationary",
 
442
  "*numboxes: 2",
 
443
  "*delay: 10",
 
444
  0
 
445
};
 
446
 
 
447
 
 
448
static XrmOptionDescRec rotzoomer_options[] = {
 
449
  { "-shm",     ".useSHM",      XrmoptionNoArg, "True"  },
 
450
  { "-no-shm",  ".useSHM",      XrmoptionNoArg, "False" },
 
451
  { "-mode",    ".mode",        XrmoptionSepArg, 0      },
 
452
  { "-move",    ".mode",        XrmoptionNoArg, "move"  },
 
453
  { "-sweep",   ".mode",        XrmoptionNoArg, "sweep" },
 
454
  { "-anim",    ".anim",        XrmoptionNoArg, "True"  },
 
455
  { "-no-anim", ".anim",        XrmoptionNoArg, "False" },
 
456
  { "-delay",   ".delay",       XrmoptionSepArg, 0      },
 
457
  { "-n",       ".numboxes",    XrmoptionSepArg, 0      },
 
458
  { 0, 0, 0, 0 }
 
459
};
 
460
 
 
461
 
 
462
XSCREENSAVER_MODULE ("Rotzoomer", rotzoomer)