/*
 * Window management.
 */

/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
#include <stdio.h>
#include <stdlib.h>
#include <X11/X.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/shape.h>
#include "dat.h"
#include "fns.h"

int isNew;

int
manage(Client *c, int mapped)
{
	int fixsize, dohide, doreshape, state;
	long msize;
	XClassHint class;
	XWMHints *hints;
	XSetWindowAttributes attrs;

	trace("manage", c, 0);
	XSelectInput(dpy, c->window, ColormapChangeMask | EnterWindowMask | PropertyChangeMask | FocusChangeMask | KeyPressMask);

	/* Get loads of hints */

	if(XGetClassHint(dpy, c->window, &class) != 0){	/* ``Success'' */
		c->instance = class.res_name;
		c->class = class.res_class;
		c->is9term = 0;
		if(isNew){
			c->is9term = strstr(c->class, "term") || strstr(c->class, "Term");
			isNew = 0;
		}
	}
	else {
		c->instance = 0;
		c->class = 0;
		c->is9term = 0;
	}
	c->iconname = getprop(c->window, XA_WM_ICON_NAME);
	c->name = getprop(c->window, XA_WM_NAME);
	setlabel(c);

	hints = XGetWMHints(dpy, c->window);
	if(XGetWMNormalHints(dpy, c->window, &c->size, &msize) == 0 || c->size.flags == 0)
		c->size.flags = PSize;		/* not specified - punt */

	getcmaps(c);
	getproto(c);
	gettrans(c);
	if(c->is9term)
		c->hold = getiprop(c->window, _rio_hold_mode);

	/* Figure out what to do with the window from hints */

	if(!getstate(c->window, &state))
		state = hints ? hints->initial_state : NormalState;
	dohide = (state == IconicState);

	fixsize = 0;
	if((c->size.flags & (USSize|PSize)))
		fixsize = 1;
	if((c->size.flags & (PMinSize|PMaxSize)) == (PMinSize|PMaxSize) && c->size.min_width == c->size.max_width && c->size.min_height == c->size.max_height)
		fixsize = 1;
	doreshape = !mapped;
	if(fixsize){
		if(c->size.flags & USPosition)
			doreshape = 0;
		if(dohide && (c->size.flags & PPosition))
			doreshape = 0;
		if(c->trans != None)
			doreshape = 0;
	}
	if(c->is9term)
		fixsize = 0;
	if(c->size.flags & PBaseSize){
		c->min_dx = c->size.base_width;
		c->min_dy = c->size.base_height;
	}
	else if(c->size.flags & PMinSize){
		c->min_dx = c->size.min_width;
		c->min_dy = c->size.min_height;
	}
	else if(c->is9term){
		c->min_dx = 100;
		c->min_dy = 50;
	}
	else
		c->min_dx = c->min_dy = 0;

	if(hints)
		XFree(hints);

	/* Now do it!!! */

	if(doreshape){
		if(0) fprintf(stderr, "in doreshape is9term=%d fixsize=%d, x=%d, y=%d, min_dx=%d, min_dy=%d, dx=%d, dy=%d\n",
				c->is9term, fixsize, c->x, c->y, c->min_dx, c->min_dy, c->dx, c->dy);
		if(current && current->screen == c->screen)
			cmapnofocus(c->screen);
		if(!c->is9term && c->x==0 && c->y==0){
			static int nwin;

			c->x = 20*nwin+BORDER;
			c->y = 20*nwin+BORDER;
			nwin++;
			nwin %= 10;
		}

		if(c->is9term && !(fixsize ? drag(c, Button3) : sweep(c, Button3))){
			XKillClient(dpy, c->window);
			rmclient(c);
			if(current && current->screen == c->screen)
				cmapfocus(current);
			return 0;
		}
	} else
		gravitate(c, 0);


	attrs.border_pixel =  c->screen->black;
	attrs.background_pixel =  c->screen->white;
	attrs.colormap = c->screen->def_cmap;
	c->parent = XCreateWindow(dpy, c->screen->root,
			c->x - BORDER, c->y - BORDER,
			c->dx + 2*BORDER, c->dy + 2*BORDER,
			0,
			c->screen->depth,
			CopyFromParent,
			c->screen->vis,
			CWBackPixel | CWBorderPixel | CWColormap,
			&attrs);

	XSelectInput(dpy, c->parent, SubstructureRedirectMask | SubstructureNotifyMask|ButtonPressMask| PointerMotionMask|LeaveWindowMask|KeyPressMask);
	if(mapped)
		c->reparenting = 1;
	if(doreshape && !fixsize)
		XResizeWindow(dpy, c->window, c->dx, c->dy);
	XSetWindowBorderWidth(dpy, c->window, 0);

	/*
	  * To have something more than only a big white or black border
	  * XXX should replace this by a pattern in the white or black
	  * such that we can see the border also if all our
	  * windows are black and/or white
	  * (black (or white)  border around black (or white) window
	  *  is not very helpful.
	  */
	if(c->screen->depth <= 8){
		XSetWindowBorderWidth(dpy, c->parent, 1);
	}

	XReparentWindow(dpy, c->window, c->parent, BORDER, BORDER);
#ifdef	SHAPE
	if(shape){
		XShapeSelectInput(dpy, c->window, ShapeNotifyMask);
		ignore_badwindow = 1;		/* magic */
		setshape(c);
		ignore_badwindow = 0;
	}
#endif
	XAddToSaveSet(dpy, c->window);
	if(dohide)
		hide(c);
	else {
		XMapWindow(dpy, c->window);
		XMapWindow(dpy, c->parent);
		XUnmapWindow(dpy, c->screen->sweepwin);
		if(nostalgia || doreshape)
			active(c);
		else if(c->trans != None && current && current->window == c->trans)
			active(c);
		else
			setactive(c, 0);
		setstate(c, NormalState);
	}
	if(current && (current != c))
		cmapfocus(current);
	c->init = 1;

	/*
	 * If we swept the window, let's send a resize event to the
	 * guy who just got resized.  It's not clear whether the apps
	 * should notice their new size via other means.  Try as I might,
	 * I can't find a way to have them notice during initdraw, so
	 * I solve the problem this way instead.		-rsc
	 */
	if(c->is9term)
		sendconfig(c);
	return 1;
}

void
scanwins(ScreenInfo *s)
{
	unsigned int i, nwins;
	Client *c;
	Window dw1, dw2, *wins;
	XWindowAttributes attr;

	XQueryTree(dpy, s->root, &dw1, &dw2, &wins, &nwins);
	for(i = 0; i < nwins; i++){
		XGetWindowAttributes(dpy, wins[i], &attr);
		if(attr.override_redirect || wins[i] == s->menuwin)
			continue;
		c = getclient(wins[i], 1);
		if(c != 0 && c->window == wins[i] && !c->init){
			c->x = attr.x;
			c->y = attr.y;
			c->dx = attr.width;
			c->dy = attr.height;
			c->border = attr.border_width;
			c->screen = s;
			c->parent = s->root;
			if(attr.map_state == IsViewable)
				manage(c, 1);
		}
	}
	XFree((void *) wins);	/* cast is to shut stoopid compiler up */
}

void
gettrans(Client *c)
{
	Window trans;

	trans = None;
	if(XGetTransientForHint(dpy, c->window, &trans) != 0)
		c->trans = trans;
	else
		c->trans = None;
}

void
withdraw(Client *c)
{
	XUnmapWindow(dpy, c->parent);
	gravitate(c, 1);
	XReparentWindow(dpy, c->window, c->screen->root, c->x, c->y);
	gravitate(c, 0);
	XRemoveFromSaveSet(dpy, c->window);
	setstate(c, WithdrawnState);

	/* flush any errors */
	ignore_badwindow = 1;
	XSync(dpy, False);
	ignore_badwindow = 0;
}

void
gravitate(Client *c, int invert)
{
	int gravity, dx, dy, delta;

	gravity = NorthWestGravity;
	if(c->size.flags & PWinGravity)
		gravity = c->size.win_gravity;

	delta = c->border-BORDER;
	switch (gravity){
	case NorthWestGravity:
		dx = 0;
		dy = 0;
		break;
	case NorthGravity:
		dx = delta;
		dy = 0;
		break;
	case NorthEastGravity:
		dx = 2*delta;
		dy = 0;
		break;
	case WestGravity:
		dx = 0;
		dy = delta;
		break;
	case CenterGravity:
	case StaticGravity:
		dx = delta;
		dy = delta;
		break;
	case EastGravity:
		dx = 2*delta;
		dy = delta;
		break;
	case SouthWestGravity:
		dx = 0;
		dy = 2*delta;
		break;
	case SouthGravity:
		dx = delta;
		dy = 2*delta;
		break;
	case SouthEastGravity:
		dx = 2*delta;
		dy = 2*delta;
		break;
	default:
		fprintf(stderr, "rio: bad window gravity %d for 0x%x\n", gravity, (int)c->window);
		return;
	}
	dx += BORDER;
	dy += BORDER;
	if(invert){
		dx = -dx;
		dy = -dy;
	}
	c->x += dx;
	c->y += dy;
}

static void
installcmap(ScreenInfo *s, Colormap cmap)
{
	if(cmap == None)
		XInstallColormap(dpy, s->def_cmap);
	else
		XInstallColormap(dpy, cmap);
}

void
cmapfocus(Client *c)
{
	int i, found;
	Client *cc;

	if(c == 0)
		return;
	else if(c->ncmapwins != 0){
		found = 0;
		for(i = c->ncmapwins-1; i >= 0; i--){
			installcmap(c->screen, c->wmcmaps[i]);
			if(c->cmapwins[i] == c->window)
				found++;
		}
		if(!found)
			installcmap(c->screen, c->cmap);
	}
	else if(c->trans != None && (cc = getclient(c->trans, 0)) != 0 && cc->ncmapwins != 0)
		cmapfocus(cc);
	else
		installcmap(c->screen, c->cmap);
}

void
cmapnofocus(ScreenInfo *s)
{
	installcmap(s, None);
}

void
getcmaps(Client *c)
{
	int n, i;
	Window *cw;
	XWindowAttributes attr;

	if(!c->init){
		ignore_badwindow = 1;
		XGetWindowAttributes(dpy, c->window, &attr);
		c->cmap = attr.colormap;
		XSync(dpy, False);
		ignore_badwindow = 0;
	}

	n = _getprop(c->window, wm_colormaps, XA_WINDOW, 100L, (void*)&cw);
	if(c->ncmapwins != 0){
		XFree((char *)c->cmapwins);
		free((char *)c->wmcmaps);
	}
	if(n <= 0){
		c->ncmapwins = 0;
		return;
	}

	c->ncmapwins = n;
	c->cmapwins = cw;

	c->wmcmaps = (Colormap*)malloc(n*sizeof(Colormap));
	for(i = 0; i < n; i++){
		if(cw[i] == c->window)
			c->wmcmaps[i] = c->cmap;
		else {
			/* flush any errors (e.g., caused by mozilla tabs) */
			ignore_badwindow = 1;
			XSelectInput(dpy, cw[i], ColormapChangeMask);
			XGetWindowAttributes(dpy, cw[i], &attr);
			c->wmcmaps[i] = attr.colormap;
			XSync(dpy, False);
			ignore_badwindow = 0;
		}
	}
}

void
setlabel(Client *c)
{
	char *label, *p;

	if(c->iconname != 0)
		label = c->iconname;
	else if(c->name != 0)
		label = c->name;
	else if(c->instance != 0)
		label = c->instance;
	else if(c->class != 0)
		label = c->class;
	else
		label = "no label";
	if((p = index(label, ':')) != 0)
		*p = '\0';
	c->label = label;
}

#ifdef	SHAPE
void
setshape(Client *c)
{
	int n, order;
	XRectangle *rect;

	/* don't try to add a border if the window is non-rectangular */
	rect = XShapeGetRectangles(dpy, c->window, ShapeBounding, &n, &order);
	if(n > 1)
		XShapeCombineShape(dpy, c->parent, ShapeBounding, BORDER, BORDER,
			c->window, ShapeBounding, ShapeSet);
	XFree((void*)rect);
}
#endif

int
_getprop(Window w, Atom a, Atom type, long len, unsigned char **p)
{
	Atom real_type;
	int format;
	unsigned long n, extra;
	int status;

	status = XGetWindowProperty(dpy, w, a, 0L, len, False, type, &real_type, &format, &n, &extra, p);
	if(status != Success || *p == 0)
		return -1;
	if(n == 0)
		XFree((void*) *p);
	/* could check real_type, format, extra here... */
	return n;
}

char *
getprop(Window w, Atom a)
{
	unsigned char *p;

	if(_getprop(w, a, XA_STRING, 100L, &p) <= 0)
		return 0;
	return (char *)p;
}

int
get1prop(Window w, Atom a, Atom type)
{
	char **p, *x;

	if(_getprop(w, a, type, 1L, (void*)&p) <= 0)
		return 0;
	x = *p;
	XFree((void*) p);
	return (int)x;
}

Window
getwprop(Window w, Atom a)
{
	return get1prop(w, a, XA_WINDOW);
}

int
getiprop(Window w, Atom a)
{
	return get1prop(w, a, XA_INTEGER);
}

void
setstate(Client *c, int state)
{
	long data[2];

	data[0] = (long) state;
	data[1] = (long) None;

	c->state = state;
	XChangeProperty(dpy, c->window, wm_state, wm_state, 32,
		PropModeReplace, (unsigned char *)data, 2);
}

int
getstate(Window w, int *state)
{
	long *p = 0;

	if(_getprop(w, wm_state, wm_state, 2L, (void*)&p) <= 0)
		return 0;

	*state = (int) *p;
	XFree((char *) p);
	return 1;
}

void
getproto(Client *c)
{
	Atom *p;
	int i;
	long n;
	Window w;

	w = c->window;
	c->proto = 0;
	if((n = _getprop(w, wm_protocols, XA_ATOM, 20L, (void*)&p)) <= 0)
		return;

	for(i = 0; i < n; i++)
		if(p[i] == wm_delete)
			c->proto |= Pdelete;
		else if(p[i] == wm_take_focus)
			c->proto |= Ptakefocus;
		else if(p[i] == wm_lose_focus)
			c->proto |= Plosefocus;

	XFree((char *) p);
}
