27
27
#include "screenhack.h"
28
#include <X11/Xutil.h>
30
29
#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, 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);
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 */
52
XImage *orig_map, *buffer_map;
56
struct zoom_area **zoom_box;
63
async_load_state *img_loader;
65
#ifdef HAVE_XSHM_EXTENSION
67
XShmSegmentInfo shm_info;
73
rotzoom (struct state *st, struct zoom_area *za)
75
int x, y, c, s, zoom, z;
76
int x2 = za->x + za->w - 1, y2 = za->y + za->h - 1;
79
z = 8100 * sin (M_PI * za->a2 / 8192);
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;
93
while (ox >= st->width)
95
while (oy >= st->height)
98
XPutPixel (st->buffer_map, x, y, XGetPixel (st->orig_map, ox, oy));
102
za->a1 += za->inc1; /* Rotation angle */
105
za->a2 += za->inc2; /* Zoom */
108
za->ox = ox; /* Save state for next iteration */
116
reset_zoom (struct state *st, struct zoom_area *za)
119
int speed = random () % 100 + 100;
120
switch (random () % 4) {
128
za->n = (st->height - 10) * 256 / speed;
133
za->x = st->width - 10;
137
za->n = (st->width - 10) * 256 / speed;
143
za->y = st->height - 10;
146
za->n = (st->height - 10) * 256 / speed;
155
za->n = (st->width - 10) * 256 / speed;
158
za->ww = st->width - za->w;
159
za->hh = st->height - za->h;
161
/* We want smaller angle increments in sweep mode (looks better) */
165
za->inc1 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
166
za->inc2 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
168
za->w = 50 + random() % 300;
169
za->h = 50 + random() % 300;
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;
176
za->ww = st->width - za->w;
177
za->hh = st->height - za->h;
179
za->x = (za->ww ? random() % za->ww : 0);
180
za->y = (za->hh ? random() % za->hh : 0);
182
za->dx = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
183
za->dy = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
186
za->n = 50 + random() % 1000;
190
za->n = 5 + random() % 10;
195
za->inc1 = ((2 * (random() & 1)) - 1) * (random () % 30);
196
za->inc2 = ((2 * (random() & 1)) - 1) * (random () % 30);
199
za->xx = za->x * 256;
200
za->yy = za->y * 256;
206
static struct zoom_area *
207
create_zoom (struct state *st)
209
struct zoom_area *za;
211
za = malloc (sizeof (struct zoom_area));
219
update_position (struct zoom_area *za)
229
za->dx = 100 + random() % 100;
234
za->dy = 100 + random() % 100;
237
if (za->x > za->ww) {
239
za->dx = -(100 + random() % 100);
242
if (za->y > za->hh) {
244
za->dy = -(100 + random() % 100);
250
DisplayImage (struct state *st, int x, int y, int w, int h)
252
#ifdef HAVE_XSHM_EXTENSION
254
XShmPutImage (st->dpy, st->window, st->gc, st->buffer_map, x, y, x, y,
257
#endif /* HAVE_XSHM_EXTENSION */
258
XPutImage(st->dpy, st->window, st->gc, st->buffer_map, x, y, x, y, w, h);
263
init_hack (struct state *st)
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);
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);
276
DisplayImage(st, 0, 0, st->width, st->height);
281
rotzoomer_draw (Display *disp, Window win, void *closure)
283
struct state *st = (struct state *) closure;
284
int delay = (st->delay * 1000);
287
if (st->img_loader) /* still loading */
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);
298
for (i = 0; i < st->num_zoom; i++) {
299
if (st->move || st->sweep)
300
update_position (st->zoom_box[i]);
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]);
308
st->zoom_box[i]->n--;
310
reset_zoom (st, st->zoom_box[i]);
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);
324
setup_X (struct state *st)
326
XWindowAttributes xgwa;
331
XGetWindowAttributes (st->dpy, st->window, &xgwa);
333
st->colormap = xgwa.colormap;
334
st->width = xgwa.width;
335
st->height = xgwa.height;
336
st->visual = xgwa.visual;
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,
354
#ifdef HAVE_XSHM_EXTENSION
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) {
360
fprintf(stderr, "create_xshm_image failed\n");
363
#endif /* HAVE_XSHM_EXTENSION */
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);
375
rotzoomer_init (Display *dpy, Window window)
377
struct state *st = (struct state *) calloc (1, sizeof(*st));
381
#ifdef HAVE_XSHM_EXTENSION
382
st->use_shm = get_boolean_resource (st->dpy, "useSHM", "Boolean");
384
st->num_zoom = get_integer_resource (st->dpy, "numboxes", "Integer");
386
s = get_string_resource (dpy, "mode", "Mode");
387
if (!s || !*s || !strcasecmp (s, "stationary"))
389
else if (!strcasecmp (s, "move"))
391
else if (!strcasecmp (s, "sweep"))
394
fprintf (stderr, "%s: bogus mode: \"%s\"\n", progname, s);
396
st->anim = get_boolean_resource (st->dpy, "anim", "Boolean");
397
st->delay = get_integer_resource (st->dpy, "delay", "Integer");
399
/* In sweep or static mode, we want only one box */
400
if (st->sweep || !st->anim)
403
/* Can't have static sweep mode */
413
rotzoomer_reshape (Display *dpy, Window window, void *closure,
414
unsigned int w, unsigned int h)
419
rotzoomer_event (Display *dpy, Window window, void *closure, XEvent *event)
425
rotzoomer_free (Display *dpy, Window window, void *closure)
427
struct state *st = (struct state *) closure;
432
static const char *rotzoomer_defaults[] = {
433
".background: black",
434
".foreground: white",
435
#ifdef HAVE_XSHM_EXTENSION
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 },
462
XSCREENSAVER_MODULE ("Rotzoomer", rotzoomer)