JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
fixed several things, nearly feature complete
[dwm.git] / client.c
index 2ff1994..6d7bd92 100644 (file)
--- a/client.c
+++ b/client.c
@@ -3,21 +3,19 @@
  * See LICENSE file for license details.
  */
 
-#include <math.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 #include <X11/Xatom.h>
 #include <X11/Xutil.h>
 
 #include "dwm.h"
 
-static void (*arrange)(Arg *) = floating;
+static void (*arrange)(Arg *) = tiling;
 
-static void
-center(Client *c)
-{
-       XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
-}
+static Rule rule[] = {
+       { "Firefox-bin", "Gecko", { [Twww] = "www" } },
+};
 
 static Client *
 next(Client *c)
@@ -29,18 +27,18 @@ next(Client *c)
 void
 zoom(Arg *arg)
 {
-       Client **l;
+       Client **l, *old;
 
-       if(!sel)
+       if(!(old = sel))
                return;
 
        for(l = &clients; *l && *l != sel; l = &(*l)->next);
        *l = sel->next;
 
-       sel->next = clients; /* pop */
-       clients = sel;
+       old->next = clients; /* pop */
+       clients = old;
+       sel = old;
        arrange(NULL);
-       center(sel);
        focus(sel);
 }
 
@@ -54,7 +52,7 @@ max(Arg *arg)
        sel->w = sw - 2 * sel->border;
        sel->h = sh - 2 * sel->border;
        craise(sel);
-       resize(sel);
+       resize(sel, False);
        discard_events(EnterWindowMask);
 }
 
@@ -102,7 +100,7 @@ floating(Arg *arg)
        arrange = floating;
        for(c = clients; c; c = c->next) {
                if(c->tags[tsel])
-                       resize(c);
+                       resize(c, True);
                else
                        ban_client(c);
        }
@@ -119,39 +117,38 @@ void
 tiling(Arg *arg)
 {
        Client *c;
-       int n, cols, rows, gw, gh, i, j;
-    float rt, fd;
+       int n, i, w, h;
 
+       w = sw - mw;
        arrange = tiling;
-       for(n = 0, c = clients; c; c = next(c->next), n++);
-       if(n) {
-               rt = sqrt(n);
-               if(modff(rt, &fd) < 0.5)
-                       rows = floor(rt);
-               else
-                       rows = ceil(rt);
-               if(rows * rows < n)
-                       cols = rows + 1;
-               else
-                       cols = rows;
+       for(n = 0, c = clients; c; c = c->next)
+               if(c->tags[tsel])
+                       n++;
 
-               gw = (sw - 2)  / cols;
-               gh = (sh - 2) / rows;
-       }
-       else
-               cols = rows = gw = gh = 0;
+       h = (n > 1) ? sh / (n - 1) : sh;
 
-       for(i = j = 0, c = clients; c; c = c->next) {
+       for(i = 0, c = clients; c; c = c->next) {
                if(c->tags[tsel]) {
-                       c->x = i * gw;
-                       c->y = j * gh;
-                       c->w = gw;
-                       c->h = gh;
-                       resize(c);
-                       if(++i == cols) {
-                               j++;
-                               i = 0;
+                       if(n == 1) {
+                               c->x = sx;
+                               c->y = sy;
+                               c->w = sw - 2 * c->border;
+                               c->h = sh - 2 * c->border;
+                       }
+                       else if(i == 0) {
+                               c->x = sx;
+                               c->y = sy;
+                               c->w = mw - 2 * c->border;
+                               c->h = sh - 2 * c->border;
+                       }
+                       else {
+                               c->x = sx + mw;
+                               c->y = sy + (i - 1) * h;
+                               c->w = w - 2 * c->border;
+                               c->h = h - 2 * c->border;
                        }
+                       resize(c, False);
+                       i++;
                }
                else
                        ban_client(c);
@@ -175,7 +172,6 @@ prevc(Arg *arg)
 
        if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) {
                craise(c);
-               center(c);
                focus(c);
        }
 }
@@ -192,7 +188,6 @@ nextc(Arg *arg)
                c = next(clients);
        if(c) {
                craise(c);
-               center(c);
                c->revert = sel;
                focus(c);
        }
@@ -309,20 +304,54 @@ lower(Client *c)
 void
 focus(Client *c)
 {
-       if(sel && sel != c) {
-               XSetWindowBorder(dpy, sel->win, dc.bg);
-               XMapWindow(dpy, sel->title);
-               draw_client(sel);
-       }
+       Client *old = sel;
+
        sel = c;
-       XUnmapWindow(dpy, c->title);
-       XSetWindowBorder(dpy, c->win, dc.fg);
+       if(old && old != c)
+               draw_client(old);
        draw_client(c);
        XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
        XFlush(dpy);
        discard_events(EnterWindowMask);
 }
 
+static void
+init_tags(Client *c)
+{
+       XClassHint ch;
+       static unsigned int len = rule ? sizeof(rule) / sizeof(rule[0]) : 0;
+       unsigned int i, j;
+       Bool matched = False;
+
+       if(!len) {
+               c->tags[tsel] = tags[tsel];
+               return;
+       }
+
+       if(XGetClassHint(dpy, c->win, &ch)) {
+               if(ch.res_class && ch.res_name) {
+                       fprintf(stderr, "%s:%s\n", ch.res_class, ch.res_name);
+                       for(i = 0; i < len; i++)
+                               if(!strncmp(rule[i].class, ch.res_class, sizeof(rule[i].class))
+                                       && !strncmp(rule[i].instance, ch.res_name, sizeof(rule[i].instance)))
+                               {
+                       fprintf(stderr, "->>>%s:%s\n", ch.res_class, ch.res_name);
+                                       for(j = 0; j < TLast; j++)
+                                               c->tags[j] = rule[i].tags[j];
+                                       matched = True;
+                                       break;
+                               }
+               }
+               if(ch.res_class)
+                       XFree(ch.res_class);
+               if(ch.res_name)
+                       XFree(ch.res_name);
+       }
+
+       if(!matched)
+               c->tags[tsel] = tags[tsel];
+}
+
 void
 manage(Window w, XWindowAttributes *wa)
 {
@@ -346,13 +375,13 @@ manage(Window w, XWindowAttributes *wa)
        twa.background_pixmap = ParentRelative;
        twa.event_mask = ExposureMask;
 
-       c->tags[tsel] = tags[tsel];
        c->title = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th,
                        0, DefaultDepth(dpy, screen), CopyFromParent,
                        DefaultVisual(dpy, screen),
                        CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
 
        update_name(c);
+       init_tags(c);
 
        for(l = &clients; *l; l = &(*l)->next);
        c->next = *l; /* *l == nil */
@@ -368,8 +397,10 @@ manage(Window w, XWindowAttributes *wa)
        XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask,
                        GrabModeAsync, GrabModeSync, None, None);
        arrange(NULL);
-       center(c);
-       focus(c);
+       if(c->tags[tsel])
+               focus(c);
+       else
+               ban_client(c);
 }
 
 void
@@ -429,14 +460,16 @@ gravitate(Client *c, Bool invert)
 
 
 void
-resize(Client *c)
+resize(Client *c, Bool inc)
 {
        XConfigureEvent e;
 
-       if(c->incw)
-               c->w -= (c->w - c->basew) % c->incw;
-       if(c->inch)
-               c->h -= (c->h - c->baseh) % c->inch;
+       if(inc) {
+               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)
@@ -520,8 +553,14 @@ void
 draw_client(Client *c)
 {
        int i;
-       if(c == sel)
+       if(c == sel) {
+               XUnmapWindow(dpy, c->title);
+               XSetWindowBorder(dpy, c->win, dc.fg);
                return;
+       }
+
+       XSetWindowBorder(dpy, c->win, dc.bg);
+       XMapWindow(dpy, c->title);
 
        dc.x = dc.y = 0;
        dc.h = c->th;