1 /* xscreensaver, Copyright (c) 1992, 1993, 1994, 1996, 1997, 1998
2 * Jamie Zawinski <jwz@netscape.com>
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
14 * by Jonas Munsin (jmunsin@iki.fi)
15 * it's a bit of a resource hog at the moment
18 * -mutiple spheres/lenses (with bounces/layering)
19 * -different distortion matrices
20 * -randomize movement a bit
21 * program idea borrowed from a screensaver on a non-*NIX OS,
22 * code based on decayscreen by Jamie Zawinski
26 #include "screenhack.h"
28 static int delay, radius, speed, size_x, size_y;
29 static XWindowAttributes xgwa;
31 static Pixmap orig_map, buffer_map;
35 static void init_distort (Display *dpy, Window window) {
40 delay = get_integer_resource ("delay", "Integer");
41 radius = get_integer_resource ("radius", "Integer");
42 speed = get_integer_resource ("speed", "Integer");
51 XGetWindowAttributes (dpy, window, &xgwa);
53 gcv.function = GXcopy;
54 gcv.subwindow_mode = IncludeInferiors;
55 gcflags = GCForeground |GCFunction;
56 if (use_subwindow_mode_p(xgwa.screen, window)) /* see grabscreen.c */
57 gcflags |= GCSubwindowMode;
58 gc = XCreateGC (dpy, window, gcflags, &gcv);
63 grab_screen_image (xgwa.screen, window);
65 orig_map = XCreatePixmap(dpy, window,
66 xgwa.width, xgwa.height, xgwa.depth);
67 XCopyArea(dpy, window,
68 orig_map, gc, 0, 0, xgwa.width, xgwa.height, 0, 0);
69 buffer_map = XCreatePixmap(dpy, window,
70 2*radius + speed, 2*radius + speed,
73 from = (int ***)malloc ((2*radius+1) * sizeof(int **));
74 for(i = 0; i <= 2*radius; i++) {
75 from[i] = (int **)malloc((2*radius+1) * sizeof(int *));
76 for (j = 0; j <= 2*radius; j++)
77 from[i][j] = (int *)malloc(2*sizeof(int));
80 /* initialize a "see-trough" matrix */
81 for (i = 0; i <= 2*radius; i++) {
82 for (j = 0 ; j <= 2*radius ; j++) {
83 from[i][j][0]=i-radius/2;
84 from[i][j][1]=j-radius/2;
88 /* initialize the distort matrix */
89 for (i = 0; i <= 2*radius; i++) {
90 for(j = 0; j <= 2*radius; j++) {
92 r = sqrt ((i-radius)*(i-radius)+(j-radius)*(j-radius));
94 r = sin(r*(M_PI_2)/radius);
96 from[i][j][0] = radius/2 + (i-radius)*r;
98 from[i][j][0] = radius/2 + (i-radius)*r;
100 from[i][j][1] = radius/2 + (j-radius)*r;
102 from[i][j][1] = radius/2 + (j-radius)*r;
107 XSetGraphicsExposures(dpy, gc, False); /* stop events from XCopyArea */
111 move_lens (int *x, int *y, int *xmove, int *ymove) {
117 *x = radius + (random() % (size_x-2*radius));
119 *y = radius + (random() % (size_y-2*radius));
120 if (*x + 3*radius/2 >= size_x)
121 *xmove = -abs(*xmove);
122 if (*x - radius/2 <= 0)
123 *xmove = abs(*xmove);
124 if (*y + 3*radius/2 >= size_y)
125 *ymove = -abs(*ymove);
126 if (*y - radius/2 <= 0)
127 *ymove = abs(*ymove);
133 static void distort (Display *dpy, Window window)
135 static int x, y, xmove=0, ymove=0;
138 move_lens (&x, &y, &xmove, &ymove);
140 XCopyArea(dpy, orig_map, buffer_map, gc,
141 x-radius/2 - xmove, y-radius/2 - ymove,
142 2*radius + abs(xmove), 2*radius + abs(ymove),
145 /* it's possible to lower the number of loop iterations by a factor
146 * of 4, but since it's the XCopyArea's which eat resources, and
147 * I've only supplied one distortion routine (which is circular),
148 * here's a check-if-inside circle variation of this for loop.
149 * Using both optimizations turns the matrix rendering into one
150 * ugly mess... I'm counting on gcc optimization ;)
153 for(i = 0 ; i <= 2*radius ; i++) {
154 for(j = 0 ; j <= 2*radius ; j++) {
155 if (((radius-i)*(radius-i) + (j-radius)*(j-radius))
157 XCopyArea (dpy, orig_map, buffer_map, gc,
160 1, 1, i + xmove, j+ymove);
165 XCopyArea(dpy, buffer_map, window, gc, 0, 0,
166 2*radius + abs(xmove), 2*radius + abs(ymove),
167 x-radius/2 - xmove, y-radius/2 - ymove);
172 char *progclass = "Distort";
174 char *defaults [] = {
175 "*dontClearRoot: True",
176 #ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */
186 XrmOptionDescRec options [] = {
187 { "-delay", ".delay", XrmoptionSepArg, 0 },
188 { "-radius", ".radius", XrmoptionSepArg, 0 },
189 { "-speed", ".speed", XrmoptionSepArg, 0 },
194 void screenhack (Display *dpy, Window window) {
195 init_distort (dpy, window);
197 distort (dpy, window);
199 if (delay) usleep (delay);