about summary refs log tree commit diff stats
path: root/dwm.c
diff options
context:
space:
mode:
Diffstat (limited to 'dwm.c')
-rw-r--r--dwm.c234
1 files changed, 85 insertions, 149 deletions
diff --git a/dwm.c b/dwm.c
index 7363396..8ddc072 100644
--- a/dwm.c
+++ b/dwm.c
@@ -163,6 +163,7 @@ static void clearurgent(Client *c);
 static void configure(Client *c);
 static void configurenotify(XEvent *e);
 static void configurerequest(XEvent *e);
+static Monitor *createmon(void);
 static void destroynotify(XEvent *e);
 static void detach(Client *c);
 static void detachstack(Client *c);
@@ -592,6 +593,22 @@ configurerequest(XEvent *e) {
 	XSync(dpy, False);
 }
 
+Monitor *
+createmon(void) {
+	Monitor *m;
+
+	if(!(m = (Monitor *)calloc(1, sizeof(Monitor))))
+		die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
+	m->tagset[0] = m->tagset[1] = 1;
+	m->mfact = mfact;
+	m->showbar = showbar;
+	m->topbar = topbar;
+	m->lt[0] = &layouts[0];
+	m->lt[1] = &layouts[1 % LENGTH(layouts)];
+	m->ltsymbol = layouts[0].symbol;
+	return m;
+}
+
 void
 destroynotify(XEvent *e) {
 	Client *c;
@@ -1005,6 +1022,19 @@ isprotodel(Client *c) {
 	return ret;
 }
 
+#ifdef XINERAMA
+static Bool
+isuniquegeom(XineramaScreenInfo *unique, size_t len, XineramaScreenInfo *info) {
+	unsigned int i;
+
+	for(i = 0; i < len; i++)
+		if(unique[i].x_org == info->x_org && unique[i].y_org == info->y_org
+		&& unique[i].width == info->width && unique[i].height == info->height)
+			return False;
+	return True;
+}
+#endif /* XINERAMA */
+
 void
 keypress(XEvent *e) {
 	unsigned int i;
@@ -1695,165 +1725,71 @@ updatebarpos(Monitor *m) {
 
 Bool
 updategeom(void) {
-	int i, j, nn = 1, n = 1;
-	Client *c;
-	Monitor *newmons = NULL, *m = NULL, *tm;
-
-	/* TODO:
-	 * This function needs to be seriously re-designed:
-	 *
-	 * #ifdef XINERAMA
-	 * 1. Determine number of already existing monitors n
-	 * 2. Determine number of monitors Xinerama reports nn
-	 * 3. if(n <= nn) {
-	 *       if(n < nn) {
-	 *          append nn-n monitors to current struct
-	 *          flag dirty
-	 *       }
-	 *       for(i = 0; i < nn; i++) {
-	 *           if(oldgeom != newgeom) {
-	 *               apply newgeom;
-	 *               flag dirty;
-	 *           }
-	 *       }
-	 *    }
-	 *    else {
-	 *       detach all clients
-	 *       destroy current monitor struct
-	 *       create new monitor struct 
-	 *       attach all clients to first monitor
-	 *       flag dirty;
-	 *    }
-	 *    return dirty flag to caller
-	 *        if dirty is seen by caller:
-	 *           re-arrange bars/pixmaps
-	 *           arrange()
-	 * #else
-	 *    don't share between XINERAMA and non-XINERAMA handling if it gets
-	 *    too ugly
-	 * #endif
-	 */
-#ifdef XINERAMA
-	XineramaScreenInfo *info = NULL;
-	Bool *flags = NULL;
-
-	if(XineramaIsActive(dpy))
-		info = XineramaQueryScreens(dpy, &n);
-	flags = (Bool *)malloc(sizeof(Bool) * n);
-	for(i = 0; i < n; i++)
-		flags[i] = False;
-	/* next double-loop seeks any combination of retrieved Xinerama info
-	 * with existing monitors, this is used to avoid unnecessary
-	 * re-allocations of monitor structs */
-	for(i = 0, nn = n; i < n; i++)
-		for(j = 0, m = mons; m; m = m->next, j++)
-			if(!flags[j]) {
-				if((flags[j] = (
-					info[i].x_org == m->mx
-					&& info[i].y_org == m->my
-					&& info[i].width == m->mw
-					&& info[i].height == m->mh)
-				))
-					--nn;
-			}
-	if(nn == 0) { /* no need to re-allocate monitors */
-		j = 0;
-		for(i = 0, m = mons; m; m = m->next, i++) {
-			m->num = info[i].screen_number;
-			if(info[i].x_org != m->mx
-			|| info[i].y_org != m->my
-			|| info[i].width != m->mw
-			|| info[i].height != m->mh)
-			{
-				m->mx = m->wx = info[i].x_org;
-				m->my = m->wy = info[i].y_org;
-				m->mw = m->ww = info[i].width;
-				m->mh = m->wh = info[i].height;
-				updatebarpos(m);
-				j++;
-			}
-		}
-		XFree(info);
-		free(flags);
-		return j > 0;
-	}
-	/* next algorithm only considers unique geometries as separate screens */
-	for(i = 0; i < n; i++)
-		flags[i] = False; /* used for ignoring certain monitors */
-	for(i = 0, nn = n; i < n; i++)
-		for(j = 0; j < n; j++)
-			if(i != j && !flags[i]) {
-				if((flags[i] = (
-					info[i].x_org == info[j].x_org
-					&& info[i].y_org == info[j].y_org
-					&& info[i].width == info[j].width
-					&& info[i].height == info[j].height)
-				))
-					--nn;
-			}
-#endif /* XINERAMA */
-	/* allocate monitor(s) for the new geometry setup */
-	for(i = 0; i < nn; i++) {
-		if(!(m = (Monitor *)malloc(sizeof(Monitor))))
-			die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
-		m->next = newmons;
-		newmons = m;
-	}
-	/* initialise monitor(s) */
+	Bool dirty = False;
+
 #ifdef XINERAMA
 	if(XineramaIsActive(dpy)) {
-		for(i = 0, m = newmons; m && i < n; i++) {
-			if(!flags[i]) { /* only use screens that aren't dublettes */
-				m->num = info[i].screen_nu
/*
 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
 * See LICENSE file for license details.
 */
#include "dwm.h"
#include <stdio.h>

/* static */

static Client *
minclient()
{
	Client *c, *min;

	for(min = c = clients; c; c = c->next)
		if(c->weight < min->weight)
			min = c;
	return min;
}


static void
reorder()
{
	Client *c, *newclients, *tail;

	newclients = tail = NULL;
	while((c = minclient())) {
		detach(c);
		if(tail) {
			c->prev = tail;
			tail->next = c;
			tail = c;
		}
		else
			tail = newclients = c;
	}
	clients = newclients;
}

static Client *
nexttiled(Client *c)
{
	for(c = getnext(c->next); c && c->isfloat; c = getnext(c->next));
	return c;
}

/* extern */

void (*arrange)(Arg *) = DEFMODE;

void
detach(Client *c)
{
	if(c->prev)
		c->prev->next = c->next;
	if(c->next)
		c->next->prev = c->prev;
	if(c == clients)
		clients = c->next;
	c->next = c->prev = NULL;
}

void
dofloat(Arg *arg)
{
	Client *c;

	maximized = False;

	for(c = clients; c; c = c->next) {
		if(isvisible(c)) {
			resize(c, True, TopLeft);
		}
		else
			ban(c);
	}
	if(!sel || !isvisible(sel))
		focus(getnext(clients));
	restack();
}

void
dotile(Arg *arg)
{
	int h, i, n, w;
	Client *c;

	maximized = False;

	w = sw - mw;
	for(n = 0, c = clients; c; c = c->next)
		if(isvisible(c) && !c->isfloat)
			n++;

	if(n > 1)
		h = (sh - bh) / (n - 1);
	else
		h = sh - bh;

	for(i = 0, c = clients; c; c = c->next) {
		if(isvisible(c)) {
			if(c->isfloat) {
				resize(c, True, TopLeft);
				continue;
			}
			if(n == 1) {
				c->x = sx;
				c->y = sy + bh;
				c->w = sw - 2;
				c->h = sh - 2 - bh;
			}
			else if(i == 0) {
				c->x = sx;
				c->y = sy + bh;
				c->w = mw - 2;
				c->h = sh - 2 - bh;
			}
			else if(h > bh) {
				c->x = sx + mw;
				c->y = sy + (i - 1) * h + bh;
				c->w = w - 2;
				if(i + 1 == n)
					c->h = sh - c->y - 2;
				else
					c->h = h - 2;
			}
			else { /* fallback if h < bh */
				c->x = sx + mw;
				c->y = sy + bh;
				c->w = w - 2;
				c->h = sh - 2 - bh;
			}
			resize(c, False, TopLeft);
			i++;
		}
		else
			ban(c);
	}
	if(!sel || !isvisible(sel))
		focus(getnext(clients));
	restack();
}

void
focusnext(Arg *arg)
{
	Client *c;
   
	if(!sel)
		return;

	if(!(c = getnext(sel->next)))
		c = getnext(clients);
	if(c) {
		focus(c);
		restack();
	}
}

void
focusprev(Arg *arg)
{
	Client *c;

	if(!sel)
		return;

	if(!(c = getprev(sel->prev))) {
		for(c = clients; c && c->next; c = c->next);
		c = getprev(c);
	}
	if(c) {
		focus(c);
		restack();
	}
}

Bool
isvisible(Client *c)
{
	unsigned int i;

	for(i = 0; i < ntags; i++)
		if(c->tags[i] && seltag[i])
			return True;
	return False;
}

void
resizecol(Arg *arg)
{
	unsigned int n;
	Client *c;

	for(n = 0, c = clients; c; c = c->next)
		if(isvisible(c) && !c->isfloat)
			n++;
	if(!sel || sel->isfloat || n < 2 || (arrange != dotile) || maximized)
		return;

	if(sel == getnext(clients)) {
		if(mw + arg->i > sw - 100 || mw + arg->i < 100)
			return;
		mw += arg->i;
	}
	else {
		if(mw - arg->i > sw - 100 || mw - arg->i < 100)
			return;
		mw -= arg->i;
	}
	arrange(NULL);
}

void
restack()
{
	static unsigned int nwins = 0;
	static Window *wins = NULL;
	unsigned int f, fi, m, mi, n;
	Client *c;
	XEvent ev;

	for(f = 0, m = 0, c = clients; c; c = c->next)
		if(isvisible(c)) {
			if(c->isfloat || arrange == dofloat)
				f++;
			else
				m++;
		}
	if(!(n = 2 * (f + m))) {
		drawstatus();
		return;
	}
	if(nwins < n) {
		nwins = n;
		wins = erealloc(wins, nwins * sizeof(Window));
	}

	fi = 0;
	mi = 2 * f;
	if(sel) {
		if(sel->isfloat || arrange == dofloat) {
			wins[fi++] = sel->twin;
			wins[fi++] = sel->win;
		}
		else {
			wins[mi++] = sel->twin;
			wins[mi++] = sel->win;
		}
	}
	for(c = clients; c; c = c->next)
		if(isvisible(c) && c != sel) {
			if(c->isfloat || arrange == dofloat) {
				wins[fi++] = c->twin;
				wins[fi++] = c->win;
			}
			else {
				wins[mi++] = c->twin;
				wins[mi++] = c->win;
			}
		}
	XRestackWindows(dpy, wins, n);
	drawall();
	XSync(dpy, False);
	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}

void
togglemode(Arg *arg)
{
	arrange = (arrange == dofloat) ? dotile : dofloat;
	if(sel)
		arrange(NULL);
	else
		drawstatus();
}

void
toggleview(Arg *arg)
{
	unsigned int i;

	seltag[arg->i] = !seltag[arg->i];
	for(i = 0; i < ntags && !seltag[i]; i++);
	if(i == ntags)
		seltag[arg->i] = True; /* cannot toggle last view */
	reorder();
	arrange(NULL);
}

void
view(Arg *arg)
{
	unsigned int i;

	for(i = 0; i < ntags; i++)
		seltag[i] = False;
	seltag[arg->i] = True;
	reorder();
	arrange(NULL);
}

void
viewall(Arg *arg)
{
	unsigned int i;

	for(i = 0; i < ntags; i++)
		seltag[i] = True;
	reorder();
	arrange(NULL);
}

void
zoom(Arg *arg)
{
	unsigned int n;
	Client *c;

	for(n = 0, c = clients; c; c = c->next)
		if(isvisible(c) && !c->isfloat)
			n++;
	if(!sel || sel->isfloat || n < 2 || (arrange != dotile) || maximized)
		return;

	if((c = sel) == nexttiled(clients))
		if(!(c = nexttiled(c)))
			return;
	detach(c);
	c->next = clients;
	clients->prev = c;
	clients = c;
	focus(c);
	arrange(NULL);
}