xbonkers.c revision ec6edca7aa42b6affd989ef91b5897f96795e40f
11c5ac21333f543680ce306d46f287d62c175d873mridge/*
21c5ac21333f543680ce306d46f287d62c175d873mridge * Add more stress to X server by moving, resizing and activating windows
31c5ac21333f543680ce306d46f287d62c175d873mridge * Author: Darrick Wong <djwong@us.ibm.com>
41c5ac21333f543680ce306d46f287d62c175d873mridge */
51c5ac21333f543680ce306d46f287d62c175d873mridge
61e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper/*
71c5ac21333f543680ce306d46f287d62c175d873mridge * Copyright (C) 2003-2006 IBM
81e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper *
91c5ac21333f543680ce306d46f287d62c175d873mridge * This program is free software; you can redistribute it and/or
101c5ac21333f543680ce306d46f287d62c175d873mridge * modify it under the terms of the GNU General Public License as
111c5ac21333f543680ce306d46f287d62c175d873mridge * published by the Free Software Foundation; either version 2 of the
121c5ac21333f543680ce306d46f287d62c175d873mridge * License, or (at your option) any later version.
131c5ac21333f543680ce306d46f287d62c175d873mridge *
141c5ac21333f543680ce306d46f287d62c175d873mridge * This program is distributed in the hope that it will be useful, but
151c5ac21333f543680ce306d46f287d62c175d873mridge * WITHOUT ANY WARRANTY; without even the implied warranty of
161c5ac21333f543680ce306d46f287d62c175d873mridge * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
171c5ac21333f543680ce306d46f287d62c175d873mridge * General Public License for more details.
181e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper *
191c5ac21333f543680ce306d46f287d62c175d873mridge * You should have received a copy of the GNU General Public License
201c5ac21333f543680ce306d46f287d62c175d873mridge * along with this program; if not, write to the Free Software
211c5ac21333f543680ce306d46f287d62c175d873mridge * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
221c5ac21333f543680ce306d46f287d62c175d873mridge * 02111-1307, USA.
231c5ac21333f543680ce306d46f287d62c175d873mridge */
241c5ac21333f543680ce306d46f287d62c175d873mridge
251c5ac21333f543680ce306d46f287d62c175d873mridge#include <stdio.h>
261c5ac21333f543680ce306d46f287d62c175d873mridge#include <sys/types.h>
271c5ac21333f543680ce306d46f287d62c175d873mridge#include <sys/stat.h>
281c5ac21333f543680ce306d46f287d62c175d873mridge#include <fcntl.h>
291c5ac21333f543680ce306d46f287d62c175d873mridge#include <unistd.h>
301c5ac21333f543680ce306d46f287d62c175d873mridge#include <stdlib.h>
311c5ac21333f543680ce306d46f287d62c175d873mridge#include <X11/Xlib.h>
321c5ac21333f543680ce306d46f287d62c175d873mridge#include <X11/Xatom.h>
331c5ac21333f543680ce306d46f287d62c175d873mridge#include <string.h>
341c5ac21333f543680ce306d46f287d62c175d873mridge#include <stdint.h>
351c5ac21333f543680ce306d46f287d62c175d873mridge#include <limits.h>
361c5ac21333f543680ce306d46f287d62c175d873mridge
371c5ac21333f543680ce306d46f287d62c175d873mridgestatic int enable_fullscreen = 0;
381c5ac21333f543680ce306d46f287d62c175d873mridge
391c5ac21333f543680ce306d46f287d62c175d873mridge#define MAX_PROPERTY_VALUE_LEN	4096
401c5ac21333f543680ce306d46f287d62c175d873mridge#define _NET_WM_STATE_TOGGLE	2
411c5ac21333f543680ce306d46f287d62c175d873mridge#define SLIDE_THRESHOLD 	32
421c5ac21333f543680ce306d46f287d62c175d873mridge
431c5ac21333f543680ce306d46f287d62c175d873mridge/* We assume that the workspace number will either be -1 or some
441c5ac21333f543680ce306d46f287d62c175d873mridge * huge number for "On All Workspaces" windows.  Presumably there
451c5ac21333f543680ce306d46f287d62c175d873mridge * aren't 1,000,000 workspaces, so that should be a safe number.
461c5ac21333f543680ce306d46f287d62c175d873mridge */
471c5ac21333f543680ce306d46f287d62c175d873mridge#define DESKTOP_MAX		1000000
481c5ac21333f543680ce306d46f287d62c175d873mridge
491c5ac21333f543680ce306d46f287d62c175d873mridge#define ACTION_MOVE_WINDOW		0
501c5ac21333f543680ce306d46f287d62c175d873mridge#define ACTION_ACTIVATE_WINDOW		1
511c5ac21333f543680ce306d46f287d62c175d873mridge#define ACTION_MAXIMIZE_WINDOW		2
521c5ac21333f543680ce306d46f287d62c175d873mridge#define ACTION_FULLSCREEN_WINDOW	3
531c5ac21333f543680ce306d46f287d62c175d873mridge#define ACTION_HIDDEN_WINDOW		4
541c5ac21333f543680ce306d46f287d62c175d873mridge#define ACTION_SLIDE_WINDOW_0		5
551c5ac21333f543680ce306d46f287d62c175d873mridge#define ACTION_SLIDE_WINDOW_1		6
561c5ac21333f543680ce306d46f287d62c175d873mridge#define ACTION_SLIDE_WINDOW_2		7
571c5ac21333f543680ce306d46f287d62c175d873mridge#define ACTION_SLIDE_WINDOW_3		8
581c5ac21333f543680ce306d46f287d62c175d873mridge#define ACTION_SLIDE_WINDOW_4		9
591c5ac21333f543680ce306d46f287d62c175d873mridge#define ACTION_SLIDE_WINDOW_5		10
601c5ac21333f543680ce306d46f287d62c175d873mridge#define ACTION_MIN		ACTION_MOVE_WINDOW
611c5ac21333f543680ce306d46f287d62c175d873mridge#define ACTION_MAX		ACTION_SLIDE_WINDOW_5
621c5ac21333f543680ce306d46f287d62c175d873mridge
631c5ac21333f543680ce306d46f287d62c175d873mridge/* The goal of this program:
641c5ac21333f543680ce306d46f287d62c175d873mridge * 0. Seed random number generator
651c5ac21333f543680ce306d46f287d62c175d873mridge * 1. Grab the list of windows and the desktop size.
661c5ac21333f543680ce306d46f287d62c175d873mridge * 2. Filter out the panel/desktop/whatever.  We're going to make
671c5ac21333f543680ce306d46f287d62c175d873mridge *    a cheesy assumption that a window on desktop -1 should be left
681c5ac21333f543680ce306d46f287d62c175d873mridge *    alone.  (Actually, the -1 denotes "all desktops")
691c5ac21333f543680ce306d46f287d62c175d873mridge * 3. For each window:
701c5ac21333f543680ce306d46f287d62c175d873mridge *    a. Figure out what we're going to do--activate, move/resize,
711c5ac21333f543680ce306d46f287d62c175d873mridge *       or maximize it.
721c5ac21333f543680ce306d46f287d62c175d873mridge *    b. If we're going to move/resize, grab 4 random numbers.
731c5ac21333f543680ce306d46f287d62c175d873mridge *    c. Actually perform the action.
741c5ac21333f543680ce306d46f287d62c175d873mridge * 4. Every so often, jump back to (2) in case there are new windows.
751c5ac21333f543680ce306d46f287d62c175d873mridge *    Maybe every 10,000 moves or so.
761c5ac21333f543680ce306d46f287d62c175d873mridge *
771c5ac21333f543680ce306d46f287d62c175d873mridge * Note that you do NOT want to run this on any X session you care about.
781c5ac21333f543680ce306d46f287d62c175d873mridge * It shouldn't take down X, but YMMV and in any case mad window resizing
791c5ac21333f543680ce306d46f287d62c175d873mridge * makes it hard to get work done.
801c5ac21333f543680ce306d46f287d62c175d873mridge */
811c5ac21333f543680ce306d46f287d62c175d873mridgestatic int seed_random(void);
821c5ac21333f543680ce306d46f287d62c175d873mridgestatic int get_desktop_size(Display *disp, unsigned long *w,
831c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long *h);
841c5ac21333f543680ce306d46f287d62c175d873mridgestatic char *get_property (Display *disp, Window win, Atom xa_prop_type,
851c5ac21333f543680ce306d46f287d62c175d873mridge	char *prop_name, unsigned long *size, unsigned long *items);
861c5ac21333f543680ce306d46f287d62c175d873mridgestatic void go_bonkers(Display *disp, unsigned long iterations,
871c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long sleep);
881c5ac21333f543680ce306d46f287d62c175d873mridgestatic Window *get_interesting_windows(Display *disp,
891c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long *num_windows);
901c5ac21333f543680ce306d46f287d62c175d873mridgestatic Window *get_client_list(Display *disp, unsigned long *size,
911c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long *items);
921c5ac21333f543680ce306d46f287d62c175d873mridgestatic long get_randnum(long min, long max);
931c5ac21333f543680ce306d46f287d62c175d873mridgestatic int send_client_msg(Display *disp, Window win, char *msg,
941e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper	unsigned long data0, unsigned long data1,
951c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long data2, unsigned long data3,
961c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long data4);
971c5ac21333f543680ce306d46f287d62c175d873mridgestatic int activate_window (Display *disp, Window *win);
981c5ac21333f543680ce306d46f287d62c175d873mridgestatic int wm_supports(Display *disp, const char *prop);
991c5ac21333f543680ce306d46f287d62c175d873mridgestatic void move_window(Display *disp, Window *win, unsigned long desk_w,
1001c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long desk_h);
1011c5ac21333f543680ce306d46f287d62c175d873mridgestatic int toggle_property(Display *disp, Window *win, const char *property);
1021c5ac21333f543680ce306d46f287d62c175d873mridgestatic inline unsigned long clamp_value(unsigned long value,
1031c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long min, unsigned long max);
1041c5ac21333f543680ce306d46f287d62c175d873mridgestatic int ignore_xlib_error(Display *disp, XErrorEvent *xee);
1051c5ac21333f543680ce306d46f287d62c175d873mridge
1061c5ac21333f543680ce306d46f287d62c175d873mridge/* Actual functions begin here. */
1071c5ac21333f543680ce306d46f287d62c175d873mridge
1081c5ac21333f543680ce306d46f287d62c175d873mridgestatic int seed_random(void) {
1091c5ac21333f543680ce306d46f287d62c175d873mridge	int fp;
1101c5ac21333f543680ce306d46f287d62c175d873mridge	long seed;
1111c5ac21333f543680ce306d46f287d62c175d873mridge
1121c5ac21333f543680ce306d46f287d62c175d873mridge	fp = open("/dev/urandom", O_RDONLY);
1131c5ac21333f543680ce306d46f287d62c175d873mridge	if (fp < 0) {
1141c5ac21333f543680ce306d46f287d62c175d873mridge		perror("/dev/urandom");
1151c5ac21333f543680ce306d46f287d62c175d873mridge		return 0;
1161c5ac21333f543680ce306d46f287d62c175d873mridge	}
1171c5ac21333f543680ce306d46f287d62c175d873mridge
1181c5ac21333f543680ce306d46f287d62c175d873mridge	if (read(fp, &seed, sizeof(seed)) != sizeof(seed)) {
1191c5ac21333f543680ce306d46f287d62c175d873mridge		perror("read random seed");
1201c5ac21333f543680ce306d46f287d62c175d873mridge		return 0;
1211c5ac21333f543680ce306d46f287d62c175d873mridge	}
1221c5ac21333f543680ce306d46f287d62c175d873mridge
1231c5ac21333f543680ce306d46f287d62c175d873mridge	close(fp);
1241c5ac21333f543680ce306d46f287d62c175d873mridge	srand(seed);
1251c5ac21333f543680ce306d46f287d62c175d873mridge
1261c5ac21333f543680ce306d46f287d62c175d873mridge	return 1;
1271c5ac21333f543680ce306d46f287d62c175d873mridge}
1281c5ac21333f543680ce306d46f287d62c175d873mridge
1291c5ac21333f543680ce306d46f287d62c175d873mridgestatic int get_desktop_size(Display *disp, unsigned long *w, unsigned long *h) {
1301c5ac21333f543680ce306d46f287d62c175d873mridge	*w = DisplayWidth(disp, 0);
1311c5ac21333f543680ce306d46f287d62c175d873mridge	*h = DisplayHeight(disp, 0);
1321c5ac21333f543680ce306d46f287d62c175d873mridge
1331c5ac21333f543680ce306d46f287d62c175d873mridge	return 1;
1341c5ac21333f543680ce306d46f287d62c175d873mridge}
1351c5ac21333f543680ce306d46f287d62c175d873mridge
1361c5ac21333f543680ce306d46f287d62c175d873mridgestatic char *get_property (Display *disp, Window win, Atom xa_prop_type,
1371c5ac21333f543680ce306d46f287d62c175d873mridge	char *prop_name, unsigned long *size, unsigned long *items)
1381c5ac21333f543680ce306d46f287d62c175d873mridge{
1391c5ac21333f543680ce306d46f287d62c175d873mridge	Atom xa_prop_name;
1401c5ac21333f543680ce306d46f287d62c175d873mridge	Atom xa_ret_type;
1411c5ac21333f543680ce306d46f287d62c175d873mridge	int ret_format;
1421c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long ret_nitems;
1431c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long ret_bytes_after;
1441c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long tmp_size;
1451c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned char *ret_prop;
1461c5ac21333f543680ce306d46f287d62c175d873mridge	char *ret;
1471e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper
1481c5ac21333f543680ce306d46f287d62c175d873mridge	xa_prop_name = XInternAtom(disp, prop_name, False);
1491e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper
1501c5ac21333f543680ce306d46f287d62c175d873mridge	if (XGetWindowProperty(disp, win, xa_prop_name, 0, MAX_PROPERTY_VALUE_LEN / 4, False,
1511e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper		xa_prop_type, &xa_ret_type, &ret_format,
1521c5ac21333f543680ce306d46f287d62c175d873mridge		&ret_nitems, &ret_bytes_after, &ret_prop) != Success)
1531c5ac21333f543680ce306d46f287d62c175d873mridge	{
1541c5ac21333f543680ce306d46f287d62c175d873mridge		fprintf(stderr, "Cannot get %s property.\n", prop_name);
1551c5ac21333f543680ce306d46f287d62c175d873mridge		return NULL;
1561c5ac21333f543680ce306d46f287d62c175d873mridge	}
1571e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper
1581c5ac21333f543680ce306d46f287d62c175d873mridge	if (xa_ret_type != xa_prop_type) {
1591c5ac21333f543680ce306d46f287d62c175d873mridge		fprintf(stderr, "Invalid type of %s property.\n", prop_name);
1601c5ac21333f543680ce306d46f287d62c175d873mridge		XFree(ret_prop);
1611c5ac21333f543680ce306d46f287d62c175d873mridge		return NULL;
1621c5ac21333f543680ce306d46f287d62c175d873mridge	}
1631c5ac21333f543680ce306d46f287d62c175d873mridge
1641c5ac21333f543680ce306d46f287d62c175d873mridge	/* XXX: EVIL HACK to get around a bug when sizeof(Window) is 8 yet ret_format
1651c5ac21333f543680ce306d46f287d62c175d873mridge	 * is listed as 32bits and we're trying to get the client list.  Just double
1661c5ac21333f543680ce306d46f287d62c175d873mridge	 * ret_format and proceed. */
1671c5ac21333f543680ce306d46f287d62c175d873mridge	if (ret_format == 32 && strcmp(prop_name, "_NET_CLIENT_LIST") == 0 &&
1681c5ac21333f543680ce306d46f287d62c175d873mridge		sizeof(Window) == 8)
1691c5ac21333f543680ce306d46f287d62c175d873mridge	{
1701c5ac21333f543680ce306d46f287d62c175d873mridge		ret_format *= 2;
1711c5ac21333f543680ce306d46f287d62c175d873mridge	}
1721c5ac21333f543680ce306d46f287d62c175d873mridge
1731c5ac21333f543680ce306d46f287d62c175d873mridge	/* null terminate the result to make string handling easier */
1741c5ac21333f543680ce306d46f287d62c175d873mridge	tmp_size = (ret_format / 8) * ret_nitems;
1751c5ac21333f543680ce306d46f287d62c175d873mridge	ret = calloc(tmp_size + 1, 1);
1761c5ac21333f543680ce306d46f287d62c175d873mridge	if (!ret) {
1771c5ac21333f543680ce306d46f287d62c175d873mridge		perror("get_property malloc failed");
1781c5ac21333f543680ce306d46f287d62c175d873mridge		return NULL;
1791c5ac21333f543680ce306d46f287d62c175d873mridge	}
1801c5ac21333f543680ce306d46f287d62c175d873mridge	memcpy(ret, ret_prop, tmp_size);
1811c5ac21333f543680ce306d46f287d62c175d873mridge	ret[tmp_size] = '\0';
1821c5ac21333f543680ce306d46f287d62c175d873mridge
1831c5ac21333f543680ce306d46f287d62c175d873mridge	if (size) {
1841c5ac21333f543680ce306d46f287d62c175d873mridge		*size = ret_format / 8;
1851c5ac21333f543680ce306d46f287d62c175d873mridge	}
1861c5ac21333f543680ce306d46f287d62c175d873mridge	if (items) {
1871c5ac21333f543680ce306d46f287d62c175d873mridge		*items = ret_nitems;
1881c5ac21333f543680ce306d46f287d62c175d873mridge	}
1891e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper
1901c5ac21333f543680ce306d46f287d62c175d873mridge	XFree(ret_prop);
1911c5ac21333f543680ce306d46f287d62c175d873mridge	return ret;
1921c5ac21333f543680ce306d46f287d62c175d873mridge}
1931c5ac21333f543680ce306d46f287d62c175d873mridge
1941c5ac21333f543680ce306d46f287d62c175d873mridgestatic long get_randnum(long min, long max) {
1951c5ac21333f543680ce306d46f287d62c175d873mridge	return min + (long)((float)max * (rand() / (RAND_MAX + 1.0)));
1961c5ac21333f543680ce306d46f287d62c175d873mridge}
1971c5ac21333f543680ce306d46f287d62c175d873mridge
1981c5ac21333f543680ce306d46f287d62c175d873mridgestatic int wm_supports(Display *disp, const char *prop) {
1991c5ac21333f543680ce306d46f287d62c175d873mridge	Atom xa_prop = XInternAtom(disp, prop, False);
2001c5ac21333f543680ce306d46f287d62c175d873mridge	Atom *list;
2011c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long size, items;
2021c5ac21333f543680ce306d46f287d62c175d873mridge	int i;
2031c5ac21333f543680ce306d46f287d62c175d873mridge
2041c5ac21333f543680ce306d46f287d62c175d873mridge	if (! (list = (Atom *)get_property(disp, DefaultRootWindow(disp),
2051c5ac21333f543680ce306d46f287d62c175d873mridge		XA_ATOM, "_NET_SUPPORTED", &size, &items)))
2061c5ac21333f543680ce306d46f287d62c175d873mridge	{
2071c5ac21333f543680ce306d46f287d62c175d873mridge		fprintf(stderr, "Cannot get _NET_SUPPORTED property.\n");
2081c5ac21333f543680ce306d46f287d62c175d873mridge		return 0;
2091c5ac21333f543680ce306d46f287d62c175d873mridge	}
2101c5ac21333f543680ce306d46f287d62c175d873mridge
2111c5ac21333f543680ce306d46f287d62c175d873mridge	size *= items;
2121c5ac21333f543680ce306d46f287d62c175d873mridge
2131c5ac21333f543680ce306d46f287d62c175d873mridge	for (i = 0; i < size / sizeof(Atom); i++) {
2141c5ac21333f543680ce306d46f287d62c175d873mridge		if (list[i] == xa_prop) {
2151c5ac21333f543680ce306d46f287d62c175d873mridge			free(list);
2161c5ac21333f543680ce306d46f287d62c175d873mridge			return 1;
2171c5ac21333f543680ce306d46f287d62c175d873mridge		}
2181c5ac21333f543680ce306d46f287d62c175d873mridge	}
2191e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper
2201c5ac21333f543680ce306d46f287d62c175d873mridge	free(list);
2211c5ac21333f543680ce306d46f287d62c175d873mridge	return 0;
2221c5ac21333f543680ce306d46f287d62c175d873mridge}
2231c5ac21333f543680ce306d46f287d62c175d873mridge
2241c5ac21333f543680ce306d46f287d62c175d873mridgestatic inline unsigned long clamp_value(unsigned long value,
2251c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long min, unsigned long max)
2261c5ac21333f543680ce306d46f287d62c175d873mridge{
2271c5ac21333f543680ce306d46f287d62c175d873mridge	return (value < min ? min : (value > max ? max : value));
2281c5ac21333f543680ce306d46f287d62c175d873mridge}
2291c5ac21333f543680ce306d46f287d62c175d873mridge
2301c5ac21333f543680ce306d46f287d62c175d873mridgestatic int ignore_xlib_error(Display *disp, XErrorEvent *xee) {
2311c5ac21333f543680ce306d46f287d62c175d873mridge	char errbuf[256];
2321c5ac21333f543680ce306d46f287d62c175d873mridge
2331c5ac21333f543680ce306d46f287d62c175d873mridge	XGetErrorText(disp, xee->error_code, errbuf, 256);
2341c5ac21333f543680ce306d46f287d62c175d873mridge	fprintf(stderr, "IGNORING Xlib error %d (%s) on request (%d.%d), sernum = %lu.\n",
2351c5ac21333f543680ce306d46f287d62c175d873mridge		xee->error_code, errbuf, xee->request_code, xee->minor_code,
2361c5ac21333f543680ce306d46f287d62c175d873mridge		xee->serial);
2371c5ac21333f543680ce306d46f287d62c175d873mridge	return 1;
2381c5ac21333f543680ce306d46f287d62c175d873mridge}
2391c5ac21333f543680ce306d46f287d62c175d873mridge
2401c5ac21333f543680ce306d46f287d62c175d873mridgestatic void slide_window(Display *disp, Window *win, unsigned long desk_w, unsigned long desk_h) {
2411c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long x, y;
2421c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long w, h;
2431c5ac21333f543680ce306d46f287d62c175d873mridge	XWindowAttributes moo;
2441c5ac21333f543680ce306d46f287d62c175d873mridge	Window junk;
2451c5ac21333f543680ce306d46f287d62c175d873mridge
2461c5ac21333f543680ce306d46f287d62c175d873mridge	if (XGetWindowAttributes(disp, *win, &moo) != 1) {
2471c5ac21333f543680ce306d46f287d62c175d873mridge		fprintf(stderr, "Cannot get attributes of window 0x%lx.\n", *win);
2481c5ac21333f543680ce306d46f287d62c175d873mridge		return;
2491c5ac21333f543680ce306d46f287d62c175d873mridge	}
2501c5ac21333f543680ce306d46f287d62c175d873mridge
2511e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper	if (XTranslateCoordinates(disp, *win, moo.root,
2521c5ac21333f543680ce306d46f287d62c175d873mridge		-moo.border_width, -moo.border_width, &moo.x, &moo.y, &junk) != 1)
2531c5ac21333f543680ce306d46f287d62c175d873mridge	{
2541c5ac21333f543680ce306d46f287d62c175d873mridge		fprintf(stderr, "Cannot translate coordinates of window 0x%lx.\n", *win);
2551c5ac21333f543680ce306d46f287d62c175d873mridge		return;
2561c5ac21333f543680ce306d46f287d62c175d873mridge	}
2571c5ac21333f543680ce306d46f287d62c175d873mridge
2581c5ac21333f543680ce306d46f287d62c175d873mridge	x = moo.x + get_randnum(-SLIDE_THRESHOLD, SLIDE_THRESHOLD);
2591c5ac21333f543680ce306d46f287d62c175d873mridge	y = moo.y + get_randnum(-SLIDE_THRESHOLD, SLIDE_THRESHOLD);
2601c5ac21333f543680ce306d46f287d62c175d873mridge	w = moo.width + get_randnum(-SLIDE_THRESHOLD, SLIDE_THRESHOLD);
2611c5ac21333f543680ce306d46f287d62c175d873mridge	h = moo.height + get_randnum(-SLIDE_THRESHOLD, SLIDE_THRESHOLD);
2621c5ac21333f543680ce306d46f287d62c175d873mridge
2631c5ac21333f543680ce306d46f287d62c175d873mridge	x = clamp_value(x, 0, desk_w);
2641c5ac21333f543680ce306d46f287d62c175d873mridge	y = clamp_value(y, 0, desk_h);
2651c5ac21333f543680ce306d46f287d62c175d873mridge	w = clamp_value(w, 0, desk_w);
2661c5ac21333f543680ce306d46f287d62c175d873mridge	h = clamp_value(h, 0, desk_h);
2671c5ac21333f543680ce306d46f287d62c175d873mridge
26843088e16aa60d69e3ec5a69cdd8bdd45b8891127Garrett Cooper	if (wm_supports(disp, "_NET_MOVERESIZE_WINDOW")) {
2691e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper		send_client_msg(disp, *win, "_NET_MOVERESIZE_WINDOW",
2701c5ac21333f543680ce306d46f287d62c175d873mridge			0, x, y, w, h);
2711c5ac21333f543680ce306d46f287d62c175d873mridge	} else {
2721c5ac21333f543680ce306d46f287d62c175d873mridge		XMoveResizeWindow(disp, *win, x, y, w, h);
2731c5ac21333f543680ce306d46f287d62c175d873mridge	}
2741c5ac21333f543680ce306d46f287d62c175d873mridge}
2751c5ac21333f543680ce306d46f287d62c175d873mridge
2761c5ac21333f543680ce306d46f287d62c175d873mridgestatic void move_window(Display *disp, Window *win, unsigned long desk_w, unsigned long desk_h) {
2771c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long x, y, w, h;
2781c5ac21333f543680ce306d46f287d62c175d873mridge
2791c5ac21333f543680ce306d46f287d62c175d873mridge	x = get_randnum(0, desk_w);
2801c5ac21333f543680ce306d46f287d62c175d873mridge	y = get_randnum(0, desk_h);
2811c5ac21333f543680ce306d46f287d62c175d873mridge	w = get_randnum(150, desk_w);
2821c5ac21333f543680ce306d46f287d62c175d873mridge	h = get_randnum(150, desk_h);
2831e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper
28443088e16aa60d69e3ec5a69cdd8bdd45b8891127Garrett Cooper	if (wm_supports(disp, "_NET_MOVERESIZE_WINDOW")) {
2851e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper		send_client_msg(disp, *win, "_NET_MOVERESIZE_WINDOW",
2861c5ac21333f543680ce306d46f287d62c175d873mridge			0, x, y, w, h);
2871c5ac21333f543680ce306d46f287d62c175d873mridge	} else {
2881c5ac21333f543680ce306d46f287d62c175d873mridge		XMoveResizeWindow(disp, *win, x, y, w, h);
2891c5ac21333f543680ce306d46f287d62c175d873mridge	}
2901c5ac21333f543680ce306d46f287d62c175d873mridge}
2911c5ac21333f543680ce306d46f287d62c175d873mridge
2921c5ac21333f543680ce306d46f287d62c175d873mridgestatic int toggle_property(Display *disp, Window *win, const char *property) {
2931c5ac21333f543680ce306d46f287d62c175d873mridge	Atom prop;
2941c5ac21333f543680ce306d46f287d62c175d873mridge
2951c5ac21333f543680ce306d46f287d62c175d873mridge	prop = XInternAtom(disp, property, False);
2961c5ac21333f543680ce306d46f287d62c175d873mridge	return send_client_msg(disp, *win, "_NET_WM_STATE",
2971c5ac21333f543680ce306d46f287d62c175d873mridge		_NET_WM_STATE_TOGGLE, prop, 0, 0, 0);
2981c5ac21333f543680ce306d46f287d62c175d873mridge}
2991c5ac21333f543680ce306d46f287d62c175d873mridge
3001c5ac21333f543680ce306d46f287d62c175d873mridgestatic void go_bonkers(Display *disp, unsigned long iterations, unsigned long sleep) {
3011c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long desk_w, desk_h;
3021c5ac21333f543680ce306d46f287d62c175d873mridge	Window *windows, *window;
3031c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long windows_length = 0, i;
3041c5ac21333f543680ce306d46f287d62c175d873mridge
3051c5ac21333f543680ce306d46f287d62c175d873mridge	if (!get_desktop_size(disp, &desk_w, &desk_h)) {
3061c5ac21333f543680ce306d46f287d62c175d873mridge		fprintf(stderr, "WARNING: Assuming desktop to be 1024x768!\n");
3071c5ac21333f543680ce306d46f287d62c175d873mridge		desk_w = 1024;
3081c5ac21333f543680ce306d46f287d62c175d873mridge		desk_h = 768;
3091c5ac21333f543680ce306d46f287d62c175d873mridge	}
3101c5ac21333f543680ce306d46f287d62c175d873mridge	printf("Desktop is %lu by %lu.\n", desk_w, desk_h);
3111c5ac21333f543680ce306d46f287d62c175d873mridge
3121c5ac21333f543680ce306d46f287d62c175d873mridge	windows = get_interesting_windows(disp, &windows_length);
3131c5ac21333f543680ce306d46f287d62c175d873mridge	if (!windows) {
3141c5ac21333f543680ce306d46f287d62c175d873mridge		usleep(1000000);
3151c5ac21333f543680ce306d46f287d62c175d873mridge		return;
3161c5ac21333f543680ce306d46f287d62c175d873mridge	}
3171c5ac21333f543680ce306d46f287d62c175d873mridge	printf("There are %lu interesting windows.\n", windows_length);
3181c5ac21333f543680ce306d46f287d62c175d873mridge
3191c5ac21333f543680ce306d46f287d62c175d873mridge	/* Bump up the iteration count so that all windows get
3201c5ac21333f543680ce306d46f287d62c175d873mridge	 * some exercise. */
3211c5ac21333f543680ce306d46f287d62c175d873mridge	iterations += iterations % windows_length;
3221c5ac21333f543680ce306d46f287d62c175d873mridge
3231c5ac21333f543680ce306d46f287d62c175d873mridge	for (i = 0; i < iterations; i++) {
3241c5ac21333f543680ce306d46f287d62c175d873mridge		window = &windows[i % windows_length];
3251c5ac21333f543680ce306d46f287d62c175d873mridge		switch (get_randnum(ACTION_MIN, ACTION_MAX)) {
3261c5ac21333f543680ce306d46f287d62c175d873mridge			case ACTION_MOVE_WINDOW:
3271c5ac21333f543680ce306d46f287d62c175d873mridge				move_window(disp, window, desk_w, desk_h);
3281c5ac21333f543680ce306d46f287d62c175d873mridge				break;
3291c5ac21333f543680ce306d46f287d62c175d873mridge			case ACTION_ACTIVATE_WINDOW:
3301c5ac21333f543680ce306d46f287d62c175d873mridge				activate_window(disp, window);
3311c5ac21333f543680ce306d46f287d62c175d873mridge				break;
3321c5ac21333f543680ce306d46f287d62c175d873mridge			case ACTION_MAXIMIZE_WINDOW:
3331c5ac21333f543680ce306d46f287d62c175d873mridge				toggle_property(disp, window,
3341c5ac21333f543680ce306d46f287d62c175d873mridge					"_NET_WM_STATE_MAXIMIZED_VERT");
3351c5ac21333f543680ce306d46f287d62c175d873mridge				toggle_property(disp, window,
3361c5ac21333f543680ce306d46f287d62c175d873mridge					"_NET_WM_STATE_MAXIMIZED_HORZ");
3371c5ac21333f543680ce306d46f287d62c175d873mridge				break;
3381c5ac21333f543680ce306d46f287d62c175d873mridge			case ACTION_FULLSCREEN_WINDOW:
3391c5ac21333f543680ce306d46f287d62c175d873mridge				if (!enable_fullscreen) break;
3401c5ac21333f543680ce306d46f287d62c175d873mridge				toggle_property(disp, window,
3411c5ac21333f543680ce306d46f287d62c175d873mridge					"_NET_WM_STATE_FULLSCREEN");
3421c5ac21333f543680ce306d46f287d62c175d873mridge				break;
3431c5ac21333f543680ce306d46f287d62c175d873mridge			case ACTION_HIDDEN_WINDOW:
3441c5ac21333f543680ce306d46f287d62c175d873mridge				toggle_property(disp, window,
3451c5ac21333f543680ce306d46f287d62c175d873mridge					"_NET_WM_STATE_HIDDEN");
3461c5ac21333f543680ce306d46f287d62c175d873mridge				break;
3471c5ac21333f543680ce306d46f287d62c175d873mridge			case ACTION_SLIDE_WINDOW_0:
3481c5ac21333f543680ce306d46f287d62c175d873mridge			case ACTION_SLIDE_WINDOW_1:
3491c5ac21333f543680ce306d46f287d62c175d873mridge			case ACTION_SLIDE_WINDOW_2:
3501c5ac21333f543680ce306d46f287d62c175d873mridge			case ACTION_SLIDE_WINDOW_3:
3511c5ac21333f543680ce306d46f287d62c175d873mridge			case ACTION_SLIDE_WINDOW_4:
3521c5ac21333f543680ce306d46f287d62c175d873mridge			case ACTION_SLIDE_WINDOW_5:
3531c5ac21333f543680ce306d46f287d62c175d873mridge				slide_window(disp, window, desk_w, desk_h);
3541c5ac21333f543680ce306d46f287d62c175d873mridge				break;
3551c5ac21333f543680ce306d46f287d62c175d873mridge		}
3561c5ac21333f543680ce306d46f287d62c175d873mridge		usleep(sleep);
3571c5ac21333f543680ce306d46f287d62c175d873mridge	}
3581c5ac21333f543680ce306d46f287d62c175d873mridge
3591c5ac21333f543680ce306d46f287d62c175d873mridge	free(windows);
3601c5ac21333f543680ce306d46f287d62c175d873mridge}
3611c5ac21333f543680ce306d46f287d62c175d873mridge
3621c5ac21333f543680ce306d46f287d62c175d873mridgestatic int send_client_msg(Display *disp, Window win, char *msg,
3631e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper	unsigned long data0, unsigned long data1,
3641c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long data2, unsigned long data3,
3651c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long data4)
3661c5ac21333f543680ce306d46f287d62c175d873mridge{
3671c5ac21333f543680ce306d46f287d62c175d873mridge	XEvent event;
3681c5ac21333f543680ce306d46f287d62c175d873mridge	long mask = SubstructureRedirectMask | SubstructureNotifyMask;
3691c5ac21333f543680ce306d46f287d62c175d873mridge
3701c5ac21333f543680ce306d46f287d62c175d873mridge	event.xclient.type = ClientMessage;
3711c5ac21333f543680ce306d46f287d62c175d873mridge	event.xclient.serial = 0;
3721c5ac21333f543680ce306d46f287d62c175d873mridge	event.xclient.send_event = True;
3731c5ac21333f543680ce306d46f287d62c175d873mridge	event.xclient.message_type = XInternAtom(disp, msg, False);
3741c5ac21333f543680ce306d46f287d62c175d873mridge	event.xclient.window = win;
3751c5ac21333f543680ce306d46f287d62c175d873mridge	event.xclient.format = 32;
3761c5ac21333f543680ce306d46f287d62c175d873mridge	event.xclient.data.l[0] = data0;
3771c5ac21333f543680ce306d46f287d62c175d873mridge	event.xclient.data.l[1] = data1;
3781c5ac21333f543680ce306d46f287d62c175d873mridge	event.xclient.data.l[2] = data2;
3791c5ac21333f543680ce306d46f287d62c175d873mridge	event.xclient.data.l[3] = data3;
3801c5ac21333f543680ce306d46f287d62c175d873mridge	event.xclient.data.l[4] = data4;
3811e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper
3821c5ac21333f543680ce306d46f287d62c175d873mridge	if (XSendEvent(disp, DefaultRootWindow(disp), False, mask, &event)) {
3831c5ac21333f543680ce306d46f287d62c175d873mridge		return 1;
3841c5ac21333f543680ce306d46f287d62c175d873mridge	} else {
3851c5ac21333f543680ce306d46f287d62c175d873mridge		fprintf(stderr, "Cannot send %s event.\n", msg);
3861c5ac21333f543680ce306d46f287d62c175d873mridge		return 0;
3871c5ac21333f543680ce306d46f287d62c175d873mridge	}
3881c5ac21333f543680ce306d46f287d62c175d873mridge}
3891c5ac21333f543680ce306d46f287d62c175d873mridge
3901c5ac21333f543680ce306d46f287d62c175d873mridgestatic int activate_window (Display *disp, Window *win) {
3911c5ac21333f543680ce306d46f287d62c175d873mridge	int ret;
3921e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper
3931e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper	ret = send_client_msg(disp, *win, "_NET_ACTIVE_WINDOW",
3941c5ac21333f543680ce306d46f287d62c175d873mridge		0, 0, 0, 0, 0);
3951c5ac21333f543680ce306d46f287d62c175d873mridge	XMapRaised(disp, *win);
3961c5ac21333f543680ce306d46f287d62c175d873mridge
3971c5ac21333f543680ce306d46f287d62c175d873mridge	return ret;
3981c5ac21333f543680ce306d46f287d62c175d873mridge}
3991c5ac21333f543680ce306d46f287d62c175d873mridge
4001c5ac21333f543680ce306d46f287d62c175d873mridgestatic Window *get_client_list(Display *disp, unsigned long *size, unsigned long *items) {
4011c5ac21333f543680ce306d46f287d62c175d873mridge	void *res;
4021c5ac21333f543680ce306d46f287d62c175d873mridge
4031e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper	if ((res = (Window *)get_property(disp, DefaultRootWindow(disp),
4041c5ac21333f543680ce306d46f287d62c175d873mridge		XA_WINDOW, "_NET_CLIENT_LIST", size, items)) == NULL)
4051c5ac21333f543680ce306d46f287d62c175d873mridge	{
4061e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper		if ((res = (Window *)get_property(disp, DefaultRootWindow(disp),
4071c5ac21333f543680ce306d46f287d62c175d873mridge			XA_CARDINAL, "_WIN_CLIENT_LIST", size, items)) == NULL)
4081c5ac21333f543680ce306d46f287d62c175d873mridge		{
4091c5ac21333f543680ce306d46f287d62c175d873mridge			fprintf(stderr, "Cannot get client list properties. \n"
4101c5ac21333f543680ce306d46f287d62c175d873mridge				"(_NET_CLIENT_LIST or _WIN_CLIENT_LIST)"
4111c5ac21333f543680ce306d46f287d62c175d873mridge			"\n");
4121c5ac21333f543680ce306d46f287d62c175d873mridge			return NULL;
4131c5ac21333f543680ce306d46f287d62c175d873mridge		}
4141c5ac21333f543680ce306d46f287d62c175d873mridge	}
4151c5ac21333f543680ce306d46f287d62c175d873mridge
4161c5ac21333f543680ce306d46f287d62c175d873mridge	return (Window *)res;
4171c5ac21333f543680ce306d46f287d62c175d873mridge}
4181c5ac21333f543680ce306d46f287d62c175d873mridge
4191c5ac21333f543680ce306d46f287d62c175d873mridgestatic Window *get_interesting_windows(Display *disp, unsigned long *num_windows) {
4201c5ac21333f543680ce306d46f287d62c175d873mridge	Window *client_list, *ret, *tmp;
4211c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long client_list_size, client_list_items, i;
4221c5ac21333f543680ce306d46f287d62c175d873mridge	long *desktop;
4231c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long num_needed = 0;
4241c5ac21333f543680ce306d46f287d62c175d873mridge
4251c5ac21333f543680ce306d46f287d62c175d873mridge	if ((client_list = get_client_list(disp, &client_list_size,
4261c5ac21333f543680ce306d46f287d62c175d873mridge		&client_list_items)) == NULL)
4271c5ac21333f543680ce306d46f287d62c175d873mridge	{
4281c5ac21333f543680ce306d46f287d62c175d873mridge		return NULL;
4291c5ac21333f543680ce306d46f287d62c175d873mridge	}
4301c5ac21333f543680ce306d46f287d62c175d873mridge
4311c5ac21333f543680ce306d46f287d62c175d873mridge
4321c5ac21333f543680ce306d46f287d62c175d873mridge	/* Figure out how many Window structs we'll ultimately need. */
4331c5ac21333f543680ce306d46f287d62c175d873mridge	for (i = 0; i < client_list_items; i++) {
4341c5ac21333f543680ce306d46f287d62c175d873mridge		/* desktop ID */
4351c5ac21333f543680ce306d46f287d62c175d873mridge		if ((desktop = (long *)get_property(disp, client_list[i],
4361c5ac21333f543680ce306d46f287d62c175d873mridge			XA_CARDINAL, "_NET_WM_DESKTOP", NULL, NULL)) == NULL)
4371c5ac21333f543680ce306d46f287d62c175d873mridge		{
4381c5ac21333f543680ce306d46f287d62c175d873mridge			desktop = (long *)get_property(disp, client_list[i],
4391c5ac21333f543680ce306d46f287d62c175d873mridge				XA_CARDINAL, "_WIN_WORKSPACE", NULL, NULL);
4401c5ac21333f543680ce306d46f287d62c175d873mridge		}
4411e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper
4421c5ac21333f543680ce306d46f287d62c175d873mridge		/* Ignore windows on unknown desktops */
4431c5ac21333f543680ce306d46f287d62c175d873mridge		if (desktop && *desktop >= 0 && *desktop < DESKTOP_MAX) {
4441c5ac21333f543680ce306d46f287d62c175d873mridge			num_needed++;
4451c5ac21333f543680ce306d46f287d62c175d873mridge			free(desktop);
4461c5ac21333f543680ce306d46f287d62c175d873mridge		}
4471c5ac21333f543680ce306d46f287d62c175d873mridge	}
4481c5ac21333f543680ce306d46f287d62c175d873mridge
4491c5ac21333f543680ce306d46f287d62c175d873mridge	ret = calloc(num_needed, sizeof(Window));
4501c5ac21333f543680ce306d46f287d62c175d873mridge	if (!ret) {
4511c5ac21333f543680ce306d46f287d62c175d873mridge		perror("get_interesting_window allocations");
4521c5ac21333f543680ce306d46f287d62c175d873mridge		free(client_list);
4531c5ac21333f543680ce306d46f287d62c175d873mridge		return NULL;
4541c5ac21333f543680ce306d46f287d62c175d873mridge	}
4551c5ac21333f543680ce306d46f287d62c175d873mridge	tmp = ret;
4561c5ac21333f543680ce306d46f287d62c175d873mridge
4571c5ac21333f543680ce306d46f287d62c175d873mridge	/* Now copy all that crud. */
4581c5ac21333f543680ce306d46f287d62c175d873mridge	for (i = 0; i < client_list_items; i++) {
4591c5ac21333f543680ce306d46f287d62c175d873mridge		/* desktop ID */
4601c5ac21333f543680ce306d46f287d62c175d873mridge		if ((desktop = (long *)get_property(disp, client_list[i],
4611c5ac21333f543680ce306d46f287d62c175d873mridge			XA_CARDINAL, "_NET_WM_DESKTOP", NULL, NULL)) == NULL)
4621c5ac21333f543680ce306d46f287d62c175d873mridge		{
4631c5ac21333f543680ce306d46f287d62c175d873mridge			desktop = (long *)get_property(disp, client_list[i],
4641c5ac21333f543680ce306d46f287d62c175d873mridge				XA_CARDINAL, "_WIN_WORKSPACE", NULL, NULL);
4651c5ac21333f543680ce306d46f287d62c175d873mridge		}
4661c5ac21333f543680ce306d46f287d62c175d873mridge
4671c5ac21333f543680ce306d46f287d62c175d873mridge		if (desktop && *desktop >= 0 && *desktop < DESKTOP_MAX) {
4681c5ac21333f543680ce306d46f287d62c175d873mridge			memcpy(tmp, &client_list[i], sizeof(Window));
4691c5ac21333f543680ce306d46f287d62c175d873mridge			tmp++;
4701c5ac21333f543680ce306d46f287d62c175d873mridge			free(desktop);
4711c5ac21333f543680ce306d46f287d62c175d873mridge		}
4721c5ac21333f543680ce306d46f287d62c175d873mridge	}
4731c5ac21333f543680ce306d46f287d62c175d873mridge	free(client_list);
4741c5ac21333f543680ce306d46f287d62c175d873mridge
4751c5ac21333f543680ce306d46f287d62c175d873mridge	*num_windows = num_needed;
4761c5ac21333f543680ce306d46f287d62c175d873mridge	return ret;
4771c5ac21333f543680ce306d46f287d62c175d873mridge}
4781c5ac21333f543680ce306d46f287d62c175d873mridge
4791c5ac21333f543680ce306d46f287d62c175d873mridge
4801c5ac21333f543680ce306d46f287d62c175d873mridgeint main(int argc, char *argv[]) {
4811c5ac21333f543680ce306d46f287d62c175d873mridge	char *disp_string = NULL;
4821c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long iterations = 10000, rounds = -1, i;
4831c5ac21333f543680ce306d46f287d62c175d873mridge	unsigned long sleep = 100000;
4841c5ac21333f543680ce306d46f287d62c175d873mridge	int opt;
4851c5ac21333f543680ce306d46f287d62c175d873mridge	Display *disp;
4861c5ac21333f543680ce306d46f287d62c175d873mridge
4871c5ac21333f543680ce306d46f287d62c175d873mridge	while ((opt = getopt(argc, argv, "d:i:r:s:f")) != -1) {
4881c5ac21333f543680ce306d46f287d62c175d873mridge		switch (opt) {
4891c5ac21333f543680ce306d46f287d62c175d873mridge			case 'd':
4901c5ac21333f543680ce306d46f287d62c175d873mridge				disp_string = optarg;
4911c5ac21333f543680ce306d46f287d62c175d873mridge				break;
4921c5ac21333f543680ce306d46f287d62c175d873mridge			case 'i':
4931c5ac21333f543680ce306d46f287d62c175d873mridge				iterations = atoi(optarg);
4941c5ac21333f543680ce306d46f287d62c175d873mridge				break;
4951c5ac21333f543680ce306d46f287d62c175d873mridge			case 'r':
4961c5ac21333f543680ce306d46f287d62c175d873mridge				rounds = atoi(optarg);
4971c5ac21333f543680ce306d46f287d62c175d873mridge				break;
4981c5ac21333f543680ce306d46f287d62c175d873mridge			case 's':
4991c5ac21333f543680ce306d46f287d62c175d873mridge				sleep = atoi(optarg);
5001c5ac21333f543680ce306d46f287d62c175d873mridge				break;
5011c5ac21333f543680ce306d46f287d62c175d873mridge			case 'f':
5021c5ac21333f543680ce306d46f287d62c175d873mridge				enable_fullscreen = 1;
5031c5ac21333f543680ce306d46f287d62c175d873mridge				break;
5041c5ac21333f543680ce306d46f287d62c175d873mridge			default:
5051c5ac21333f543680ce306d46f287d62c175d873mridge				fprintf(stderr,
5061c5ac21333f543680ce306d46f287d62c175d873mridge"Usage: %s [-d DISPLAY] [-i ITERATIONS] [-r ROUNDS] [-s SLEEP] [-f]\n\
5071c5ac21333f543680ce306d46f287d62c175d873mridge	DISPLAY is an X11 display string.\n\
5081c5ac21333f543680ce306d46f287d62c175d873mridge	ITERATIONS is the approximate number of windows to play with before generating a new window list.\n\
5091c5ac21333f543680ce306d46f287d62c175d873mridge	SLEEP is the amount of time (in usec) to sleep between window tweaks.\n\
5101c5ac21333f543680ce306d46f287d62c175d873mridge	-f enables fullscreen toggling.\n\
5111c5ac21333f543680ce306d46f287d62c175d873mridge	ROUNDS is the number of iterations to run, or -1 to run forever.\n", argv[0]);
5121c5ac21333f543680ce306d46f287d62c175d873mridge				return 0;
5131c5ac21333f543680ce306d46f287d62c175d873mridge		}
5141c5ac21333f543680ce306d46f287d62c175d873mridge	}
5151c5ac21333f543680ce306d46f287d62c175d873mridge
5161c5ac21333f543680ce306d46f287d62c175d873mridge	if (!(disp = XOpenDisplay(disp_string))) {
5171c5ac21333f543680ce306d46f287d62c175d873mridge		fprintf(stderr, "Unable to connect to display '%s'.\n",
5181c5ac21333f543680ce306d46f287d62c175d873mridge			(disp_string != NULL ? disp_string : getenv("DISPLAY")));
5191c5ac21333f543680ce306d46f287d62c175d873mridge		return 1;
5201c5ac21333f543680ce306d46f287d62c175d873mridge	}
5211c5ac21333f543680ce306d46f287d62c175d873mridge
5221c5ac21333f543680ce306d46f287d62c175d873mridge	seed_random();
5231c5ac21333f543680ce306d46f287d62c175d873mridge
5241c5ac21333f543680ce306d46f287d62c175d873mridge	XSetErrorHandler(&ignore_xlib_error);
5251c5ac21333f543680ce306d46f287d62c175d873mridge
5261c5ac21333f543680ce306d46f287d62c175d873mridge	for (i = 0; i < rounds || rounds == -1; i++) {
5271c5ac21333f543680ce306d46f287d62c175d873mridge		go_bonkers(disp, iterations, sleep);
5281c5ac21333f543680ce306d46f287d62c175d873mridge	}
5291c5ac21333f543680ce306d46f287d62c175d873mridge
5301c5ac21333f543680ce306d46f287d62c175d873mridge	printf("Enough of that; I'm done.\n");
5311c5ac21333f543680ce306d46f287d62c175d873mridge
5321c5ac21333f543680ce306d46f287d62c175d873mridge	XCloseDisplay(disp);
5331c5ac21333f543680ce306d46f287d62c175d873mridge
5341c5ac21333f543680ce306d46f287d62c175d873mridge	return 0;
535ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman}
536