/*
 * Window management.
 */

/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.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)(uintptr_t)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);
}
