#include <stdio.h>
#include <X/Xlib.h>
#include <signal.h>
#include <math.h>

#define MAXWIN 24

/* Bounce, by Steven Grady */

#define abs(x) ((x) > 0 ? x : (-x))
struct window {
	Window win;
	WindowInfo winf;
	float v;
};

int totwin;
float elast = 0.5, el, gravity = 2.0;
int bottom;
int beep;
int dontfix = 0;

void SetDone();
extern int done;

bounce(d,w)
	Display		*d;
	Window		w;
{
	struct window	wind;
	WindowInfo	old_info;

	signal(SIGINT, SetDone);
	
	done = 0;
	wind.win = w;
	XQueryWindow(w, &wind.winf);
	wind.v = 0;
	old_info = wind.winf;

	if (old_info.mapped != IsMapped) {
		signal(SIGINT,SIG_DFL);
		return;
	}
	
	el = elast * 1.2; /* Make up for some of the rounding */
	bottom = DisplayHeight() - 3; /*Give allowance for a reasonable borde*/
	do {
		calc_windows(&wind);
		disp_windows(&wind);
		XSync(0);
	} while (!stopped(&wind) && !done);

	/* Restore window position */
	if (!dontfix) {
		XMoveWindow(w, old_info.x, old_info.y);
		XMapWindow(w);
		XFlush();
	}
	signal(SIGINT,SIG_DFL);
}

stopped(w)
struct window *w;
{

	if (abs(w->v) < (float) gravity) {
		return((int) abs(bottom - (w->winf.y + w->winf.height))
				< 10);
	} else
		return(0);
}

calc_windows(win)
struct window *win;
{
	int new_y;
	float new_v;

	new_y = win->winf.y + win->v;
	new_v = win->v + gravity;
	if (new_y+win->winf.height > bottom) {
		new_y = 2*bottom-(new_y+2*win->winf.height);
		if (beep) {
			XFeep((int) log((double) (win->v*win->v *
				sqrt((float) win->winf.height) / 30)) - 6);
		}
		new_v = -new_v*el;
		el *= 0.8;
	}
	win->winf.y = new_y;
	win->v = new_v;
}

disp_windows(win)
struct window *win;
{
	int i;

	XMoveWindow(win->win, win->winf.x, win->winf.y);
	XMapWindow(win->win);
	XFlush();
}


