about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--client.c50
-rw-r--r--event.c20
-rw-r--r--kb.c2
-rw-r--r--mouse.c52
-rw-r--r--wm.h13
5 files changed, 67 insertions, 70 deletions
diff --git a/client.c b/client.c
index c11d5d5..b1b1417 100644
--- a/client.c
+++ b/client.c
@@ -44,6 +44,24 @@ update_name(Client *c)
 }
 
 void
+update_size(Client *c)
+{
+	XSizeHints size;
+	long msize;
+	if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags)
+		size.flags = PSize;
+	c->flags = size.flags;
+	c->basew = size.base_width;
+	c->baseh = size.base_height;
+	c->incw = size.width_inc;
+	c->inch = size.height_inc;
+	c->maxw = size.max_width;
+	c->maxh = size.max_height;
+	c->minw = size.min_width;
+	c->minh = size.min_height;
+}
+
+void
 focus(Client *c)
 {
 	Client **l;
@@ -62,31 +80,24 @@ manage(Window w, XWindowAttributes *wa)
 {
 	Client *c, **l;
 	XSetWindowAttributes twa;
-	long msize;
 
 	c = emallocz(sizeof(Client));
 	c->win = w;
-	c->r[RFloat].x = wa->x;
-	c->r[RFloat].y = wa->y;
-	c->r[RFloat].width = wa->width;
-	c->r[RFloat].height = wa->height;
+	c->x = wa->x;
+	c->y = wa->y;
+	c->w = wa->width;
+	c->h = wa->height;
+	update_size(c);
 	XSetWindowBorderWidth(dpy, c->win, 1);
 	XSelectInput(dpy, c->win, CLIENT_MASK);
 	XGetTransientForHint(dpy, c->win, &c->trans);
-	if(!XGetWMNormalHints(dpy, c->win, &c->size, &msize) || !c->size.flags)
-		c->size.flags = PSize;
-	c->fixedsize =
-		(c->size.flags & PMinSize && c->size.flags & PMaxSize
-		 && c->size.min_width == c->size.max_width
-		 && c->size.min_height == c->size.max_height);
 	update_name(c);
 	twa.override_redirect = 1;
 	twa.background_pixmap = ParentRelative;
 	twa.event_mask = ExposureMask;
 
-	c->title = XCreateWindow(dpy, root, c->r[RFloat].x, c->r[RFloat].y,
-			c->r[RFloat].width, barrect.height, 0,
-			DefaultDepth(dpy, screen), CopyFromParent,
+	c->title = XCreateWindow(dpy, root, c->x, c->y, c->w, barrect.height,
+			0, DefaultDepth(dpy, screen), CopyFromParent,
 			DefaultVisual(dpy, screen),
 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
 
@@ -110,15 +121,14 @@ resize(Client *c)
 {
 	XConfigureEvent e;
 
-	XMoveResizeWindow(dpy, c->win, c->r[RFloat].x, c->r[RFloat].y,
-			c->r[RFloat].width, c->r[RFloat].height);
+	XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
 	e.type = ConfigureNotify;
 	e.event = c->win;
 	e.window = c->win;
-	e.x = c->r[RFloat].x;
-	e.y = c->r[RFloat].y;
-	e.width = c->r[RFloat].width;
-	e.height = c->r[RFloat].height;
+	e.x = c->x;
+	e.y = c->y;
+	e.width = c->w;
+	e.height = c->h;
 	e.border_width = 0;
 	e.above = None;
 	e.override_redirect = False;
diff --git a/event.c b/event.c
index b8b39a4..84b0698 100644
--- a/event.c
+++ b/event.c
@@ -79,13 +79,13 @@ configurerequest(XEvent *e)
 	ev->value_mask &= ~CWSibling;
 	if((c = getclient(ev->window))) {
 		if(ev->value_mask & CWX)
-			c->r[RFloat].x = ev->x;
+			c->x = ev->x;
 		if(ev->value_mask & CWY)
-			c->r[RFloat].y = ev->y;
+			c->y = ev->y;
 		if(ev->value_mask & CWWidth)
-			c->r[RFloat].width = ev->width;
+			c->w = ev->width;
 		if(ev->value_mask & CWHeight)
-			c->r[RFloat].height = ev->height;
+			c->h = ev->height;
 	}
 
 	wc.x = ev->x;
@@ -179,7 +179,6 @@ static void
 propertynotify(XEvent *e)
 {
 	XPropertyEvent *ev = &e->xproperty;
-	long msize;
 	Client *c;
 
 	if(ev->state == PropertyDelete)
@@ -195,16 +194,9 @@ propertynotify(XEvent *e)
 			case XA_WM_TRANSIENT_FOR:
 				XGetTransientForHint(dpy, c->win, &c->trans);
 				break;
+				update_size(c);
 			case XA_WM_NORMAL_HINTS:
-				if(!XGetWMNormalHints(dpy, c->win, &c->size, &msize)
-						|| !c->size.flags)
-					c->size.flags = PSize;
-				if(c->size.flags & PMinSize && c->size.flags & PMaxSize
-						&& c->size.min_width == c->size.max_width
-						&& c->size.min_height == c->size.max_height)
-					c->fixedsize = True;
-				else
-					c->fixedsize = False;
+				update_size(c);
 				break;
 		}
 		if(ev->atom == XA_WM_NAME || ev->atom == net_atom[NetWMName]) {
diff --git a/kb.c b/kb.c
index 7caae15..b9cf1cb 100644
--- a/kb.c
+++ b/kb.c
@@ -8,7 +8,7 @@
 #include <X11/keysym.h>
 
 static const char *term[] = { 
-	"xterm", "-u8", "-bg", "black", "-fg", "white", "-fn",
+	"xterm", "-bg", "black", "-fg", "white", "-fn",
 	"-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*", 0 
 };
 
diff --git a/mouse.c b/mouse.c
index 07b533c..577f23c 100644
--- a/mouse.c
+++ b/mouse.c
@@ -16,22 +16,22 @@
 static void
 mmatch(Client *c, int x1, int y1, int x2, int y2)
 {
-	c->r[RFloat].width = abs(x1 - x2);
-	c->r[RFloat].height = abs(y1 - y2);
-	c->r[RFloat].width -=
-		(c->r[RFloat].width - c->size.base_width) % c->size.width_inc;
-	c->r[RFloat].height -=
-		(c->r[RFloat].height - c->size.base_height) % c->size.height_inc;
-	if(c->size.min_width && c->r[RFloat].width < c->size.min_width)
-		c->r[RFloat].width = c->size.min_width;
-	if(c->size.min_height && c->r[RFloat].height < c->size.min_height)
-		c->r[RFloat].height = c->size.min_height;
-	if(c->size.max_width && c->r[RFloat].width > c->size.max_width)
-		c->r[RFloat].width = c->size.max_width;
-	if(c->size.max_height && c->r[RFloat].height > c->size.max_height)
-		c->r[RFloat].height = c->size.max_height;
-	c->r[RFloat].x = (x1 <= x2) ? x1 : x1 - c->r[RFloat].width;
-	c->r[RFloat].y = (y1 <= y2) ? y1 : y1 - c->r[RFloat].height;
+	c->w = abs(x1 - x2);
+	c->h = abs(y1 - y2);
+	if(c->incw)
+		c->w -= (c->w - c->basew) % c->incw;
+	if(c->inch)
+		c->h -= (c->h - c->baseh) % c->inch;
+	if(c->minw && c->w < c->minw)
+		c->w = c->minw;
+	if(c->minh && c->h < c->minh)
+		c->h = c->minh;
+	if(c->maxw && c->w > c->maxw)
+		c->w = c->maxw;
+	if(c->maxh && c->h > c->maxh)
+		c->h = c->maxh;
+	c->x = (x1 <= x2) ? x1 : x1 - c->w;
+	c->y = (y1 <= y2) ? y1 : y1 - c->h;
 }
 
 void
@@ -40,14 +40,13 @@ mresize(Client *c)
 	XEvent ev;
 	int old_cx, old_cy;
 
-	old_cx = c->r[RFloat].x;
-	old_cy = c->r[RFloat].y;
+	old_cx = c->x;
+	old_cy = c->y;
 	if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync,
 				None, cursor[CurResize], CurrentTime) != GrabSuccess)
 		return;
 	XGrabServer(dpy);
-	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0,
-			c->r[RFloat].width, c->r[RFloat].height);
+	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w, c->h);
 	for(;;) {
 		XMaskEvent(dpy, MouseMask, &ev);
 		switch(ev.type) {
@@ -55,7 +54,7 @@ mresize(Client *c)
 		case MotionNotify:
 			XUngrabServer(dpy);
 			mmatch(c, old_cx, old_cy, ev.xmotion.x, ev.xmotion.y);
-			XResizeWindow(dpy, c->win, c->r[RFloat].width, c->r[RFloat].height);
+			XResizeWindow(dpy, c->win, c->w, c->h);
 			XGrabServer(dpy);
 			break;
 		case ButtonRelease:
@@ -75,8 +74,8 @@ mmove(Client *c)
 	unsigned int dui;
 	Window dummy;
 
-	old_cx = c->r[RFloat].x;
-	old_cy = c->r[RFloat].y;
+	old_cx = c->x;
+	old_cy = c->y;
 	if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync,
 				None, cursor[CurMove], CurrentTime) != GrabSuccess)
 		return;
@@ -88,10 +87,9 @@ mmove(Client *c)
 		default: break;
 		case MotionNotify:
 			XUngrabServer(dpy);
-			c->r[RFloat].x = old_cx + (ev.xmotion.x - x1);
-			c->r[RFloat].y = old_cy + (ev.xmotion.y - y1);
-			XMoveResizeWindow(dpy, c->win, c->r[RFloat].x, c->r[RFloat].y,
-					c->r[RFloat].width, c->r[RFloat].height);
+			c->x = old_cx + (ev.xmotion.x - x1);
+			c->y = old_cy + (ev.xmotion.y - y1);
+			XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
 			XGrabServer(dpy);
 			break;
 		case ButtonRelease:
diff --git a/wm.h b/wm.h
index b647a3e..a24b40d 100644
--- a/wm.h
+++ b/wm.h
@@ -21,19 +21,15 @@ enum { NetSupported, NetWMName, NetLast };
 /* cursor */
 enum { CurNormal, CurResize, CurMove, CurInput, CurLast };
 
-/* rects */
-enum { RFloat, RGrid, RLast };
-
 struct Client {
-	char name[256];
-	char tag[256];
+	char name[256], tag[256];
 	int proto;
-	Bool fixedsize;
+	int x, y, w, h;
+	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
+	long flags; 
 	Window win;
 	Window trans;
 	Window title;
-	XSizeHints size;
-	XRectangle r[RLast];
 	Client *next;
 	Client *snext;
 };
@@ -75,6 +71,7 @@ extern void focus(Client *c);
 extern void update_name(Client *c);
 extern void draw_client(Client *c);
 extern void resize(Client *c);
+extern void update_size(Client *c);
 
 /* event.c */
 extern unsigned int discard_events(long even_mask);
#include <stdlib.h> #include <string.h> #include <X11/Xatom.h> #include <X11/Xutil.h> /* static functions */ static void grabbuttons(Client *c, Bool focus) { XUngrabButton(dpy, AnyButton, AnyModifier, c->win); if(focus) { XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button1, MODKEY | LockMask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button1, MODKEY | numlockmask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button1, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button2, MODKEY | LockMask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button2, MODKEY | numlockmask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button2, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button3, MODKEY | LockMask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button3, MODKEY | numlockmask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button3, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); } else XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); } static void resizetitle(Client *c) { c->tw = textw(c->name); if(c->tw > c->w) c->tw = c->w + 2; c->tx = c->x + c->w - c->tw + 2; c->ty = c->y; if(isvisible(c)) XMoveResizeWindow(dpy, c->twin, c->tx, c->ty, c->tw, c->th); else XMoveResizeWindow(dpy, c->twin, c->tx + 2 * sw, c->ty, c->tw, c->th); } static int xerrordummy(Display *dsply, XErrorEvent *ee) { return 0; } /* extern functions */ void ban(Client *c) { XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); XMoveWindow(dpy, c->twin, c->tx + 2 * sw, c->ty); } void focus(Client *c) { Client *old; if(!issel) return; if(!sel) sel = c; else if(sel != c) { if(maximized) togglemax(NULL); old = sel; sel = c; if(old) { grabbuttons(old, False); drawtitle(old); } } if(c) { grabbuttons(c, True); drawtitle(c); XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); } else XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); } Client * getclient(Window w) { Client *c; for(c = clients; c; c = c->next) if(c->win == w) return c; return NULL; } Client * getctitle(Window w) { Client *c; for(c = clients; c; c = c->next) if(c->twin == w) return c; return NULL; } void gravitate(Client *c, Bool invert) { int dx = 0, dy = 0; switch(c->grav) { default: break; case StaticGravity: case NorthWestGravity: case NorthGravity: case NorthEastGravity: dy = c->border; break; case EastGravity: case CenterGravity: case WestGravity: dy = -(c->h / 2) + c->border; break; case SouthEastGravity: case SouthGravity: case SouthWestGravity: dy = -(c->h); break; } switch (c->grav) { default: break; case StaticGravity: case NorthWestGravity: case WestGravity: case SouthWestGravity: dx = c->border; break; case NorthGravity: case CenterGravity: case SouthGravity: dx = -(c->w / 2) + c->border; break; case NorthEastGravity: case EastGravity: case SouthEastGravity: dx = -(c->w + c->border); break; } if(invert) { dx = -dx; dy = -dy; } c->x += dx; c->y += dy; } void killclient(Arg *arg) { if(!sel) return; if(sel->proto & PROTODELWIN) sendevent(sel->win, wmatom[WMProtocols], wmatom[WMDelete]); else XKillClient(dpy, sel->win); } void manage(Window w, XWindowAttributes *wa) { unsigned int i; Client *c; Window trans; XSetWindowAttributes twa; c = emallocz(sizeof(Client)); c->tags = emallocz(ntags * sizeof(Bool)); c->win = w; c->x = c->tx = wa->x; c->y = c->ty = wa->y; c->w = c->tw = wa->width; c->h = wa->height; c->th = bh; c->border = 0; setsize(c); if(c->x + c->w + 2 > sw) c->x = sw - c->w - 2; if(c->x < 0) c->x = 0; if(c->y + c->h + 2 > sh) c->y = sh - c->h - 2; if(c->h != sh && c->y < bh) c->y = bh; c->proto = getproto(c->win); XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | EnterWindowMask); XGetTransientForHint(dpy, c->win, &trans); twa.override_redirect = 1; twa.background_pixmap = ParentRelative; twa.event_mask = ExposureMask | EnterWindowMask; c->twin = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th, 0, DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen), CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa); grabbuttons(c, False); settags(c, getclient(trans)); if(!c->isfloat) c->isfloat = trans || (c->maxw && c->minw && c->maxw == c->minw && c->maxh == c->minh); if(clients) clients->prev = c; c->next = clients; clients = c; settitle(c); ban(c); XMapWindow(dpy, c->win); XMapWindow(dpy, c->twin); if(isvisible(c)) focus(c); arrange(NULL); } void resize(Client *c, Bool sizehints, Corner sticky) { int bottom = c->y + c->h; int right = c->x + c->w; XWindowChanges wc; if(sizehints) { if(c->incw) c->w -= (c->w - c->basew) % c->incw; if(c->inch) c->h -= (c->h - c->baseh) % c->inch; if(c->minw && c->w < c->minw) c->w = c->minw; if(c->minh && c->h < c->minh) c->h = c->minh; if(c->maxw && c->w > c->maxw) c->w = c->maxw; if(c->maxh && c->h > c->maxh) c->h = c->maxh; } if(sticky == TopRight || sticky == BotRight) c->x = right - c->w; if(sticky == BotLeft || sticky == BotRight) c->y = bottom - c->h; resizetitle(c); wc.x = c->x; wc.y = c->y; wc.width = c->w; wc.height = c->h; if(c->w == sw && c->h == sh) wc.border_width = 0; else wc.border_width = 1; XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); XSync(dpy, False); } void setsize(Client *c) { long msize; XSizeHints size; if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags) size.flags = PSize; c->flags = size.flags; if(c->flags & PBaseSize) { c->basew = size.base_width; c->baseh = size.base_height; } else c->basew = c->baseh = 0; if(c->flags & PResizeInc) { c->incw = size.width_inc; c->inch = size.height_inc; } else c->incw = c->inch = 0; if(c->flags & PMaxSize) { c->maxw = size.max_width; c->maxh = size.max_height; } else c->maxw = c->maxh = 0; if(c->flags & PMinSize) { c->minw = size.min_width; c->minh = size.min_height; } else c->minw = c->minh = 0; if(c->flags & PWinGravity) c->grav = size.win_gravity; else c->grav = NorthWestGravity; } void settitle(Client *c) { char **list = NULL; int n; XTextProperty name; name.nitems = 0; c->name[0] = 0; XGetTextProperty(dpy, c->win, &name, netatom[NetWMName]); if(!name.nitems) XGetWMName(dpy, c->win, &name); if(!name.nitems) return; if(name.encoding == XA_STRING) strncpy(c->name, (char *)name.value, sizeof(c->name)); else { if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { strncpy(c->name, *list, sizeof(c->name)); XFreeStringList(list); } } XFree(name.value); resizetitle(c); } void togglemax(Arg *arg) { int ox, oy, ow, oh; Client *c; XEvent ev; if(!sel) return; if((maximized = !maximized)) { ox = sel->x; oy = sel->y; ow = sel->w; oh = sel->h; sel->x = sx; sel->y = sy + bh; sel->w = sw - 2; sel->h = sh - 2 - bh; restack(); for(c = getnext(clients); c; c = getnext(c->next)) if(c != sel) ban(c); resize(sel, arrange == dofloat, TopLeft); sel->x = ox; sel->y = oy; sel->w = ow; sel->h = oh; } else arrange(NULL); while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); } void unmanage(Client *c) { Client *tc, *fc; Window trans; XGrabServer(dpy); XSetErrorHandler(xerrordummy); detach(c); if(sel == c) { XGetTransientForHint(dpy, c->win, &trans); if(trans && (tc = getclient(trans)) && isvisible(tc)) fc = tc; else fc = getnext(clients); focus(fc); } XUngrabButton(dpy, AnyButton, AnyModifier, c->win); XDestroyWindow(dpy, c->twin); free(c->tags); free(c); XSync(dpy, False); XSetErrorHandler(xerror); XUngrabServer(dpy); arrange(NULL); }