JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
added several other stuff
authorAnselm R. Garbe <garbeam@wmii.de>
Mon, 10 Jul 2006 20:16:48 +0000 (22:16 +0200)
committerAnselm R. Garbe <garbeam@wmii.de>
Mon, 10 Jul 2006 20:16:48 +0000 (22:16 +0200)
12 files changed:
Makefile
bar.c [new file with mode: 0644]
client.c [new file with mode: 0644]
config.h
draw.c
draw.h
event.c [new file with mode: 0644]
menu.c
util.c
util.h
wm.c
wm.h

index 7a74149..c5c8db4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,11 +3,11 @@
 
 include config.mk
 
 
 include config.mk
 
-WMSRC = wm.c draw.c util.c
+WMSRC = bar.c client.c draw.c event.c util.c wm.c
 WMOBJ = ${WMSRC:.c=.o}
 MENSRC = menu.c draw.c util.c
 MENOBJ = ${MENSRC:.c=.o}
 WMOBJ = ${WMSRC:.c=.o}
 MENSRC = menu.c draw.c util.c
 MENOBJ = ${MENSRC:.c=.o}
-MAN = gridwm.1
+MAN1 = gridwm.1 gridmenu.1
 BIN = gridwm gridmenu     
 
 all: config gridwm gridmenu
 BIN = gridwm gridmenu     
 
 all: config gridwm gridmenu
diff --git a/bar.c b/bar.c
new file mode 100644 (file)
index 0000000..8d4fb36
--- /dev/null
+++ b/bar.c
@@ -0,0 +1,18 @@
+/*
+ * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+
+#include "wm.h"
+
+void
+draw_bar()
+{
+       brush.rect = barrect;
+       brush.rect.x = brush.rect.y = 0;
+       draw(dpy, &brush, False, 0);
+
+       XCopyArea(dpy, brush.drawable, barwin, brush.gc, 0, 0, barrect.width,
+                       barrect.height, 0, 0);
+       XFlush(dpy);
+}
diff --git a/client.c b/client.c
new file mode 100644 (file)
index 0000000..a5141ea
--- /dev/null
+++ b/client.c
@@ -0,0 +1,89 @@
+/*
+ * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+
+#include <string.h>
+#include <X11/Xatom.h>
+
+#include "util.h"
+#include "wm.h"
+
+static void
+update_client_name(Client *c)
+{
+       XTextProperty name;
+       int n;
+       char **list = 0;
+
+       name.nitems = 0;
+       c->name[0] = 0;
+       XGetTextProperty(dpy, c->win, &name, net_atom[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);
+}
+
+Client *
+create_client(Window w, XWindowAttributes *wa)
+{
+       Client *c;
+       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->border = wa->border_width;
+       XSetWindowBorderWidth(dpy, c->win, 0);
+       c->proto = win_proto(c->win);
+       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);
+       XAddToSaveSet(dpy, c->win);
+       update_client_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,
+                       DefaultVisual(dpy, screen),
+                       CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
+       XFlush(dpy);
+
+#if 0
+       for(t=&client, i=0; *t; t=&(*t)->next, i++);
+       c->next = *t; /* *t == nil */
+       *t = c;
+#endif
+       return c;
+}
+
+void
+manage(Client *c)
+{
+       XMapRaised(dpy, c->win);
+       XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
+       XFlush(dpy);
+}
index 6a768b6..ca05aa2 100644 (file)
--- a/config.h
+++ b/config.h
@@ -4,6 +4,6 @@
  */
 
 #define FONT           "-*-terminus-medium-*-*-*-14-*-*-*-*-*-iso10646-*"
  */
 
 #define FONT           "-*-terminus-medium-*-*-*-14-*-*-*-*-*-iso10646-*"
-#define FGCOLOR                "#000000"
-#define BGCOLOR                "#ffaa00"
+#define BGCOLOR                "#000000"
+#define FGCOLOR                "#ffaa00"
 #define BORDERCOLOR    "#000000"
 #define BORDERCOLOR    "#000000"
diff --git a/draw.c b/draw.c
index cf7f14e..b89c365 100644 (file)
--- a/draw.c
+++ b/draw.c
@@ -162,3 +162,9 @@ loadfont(Display *dpy, Fnt *font, const char *fontstr)
        }
        font->height = font->ascent + font->descent;
 }
        }
        font->height = font->ascent + font->descent;
 }
+
+unsigned int
+labelheight(Fnt *font)
+{
+       return font->height + 4;
+}
diff --git a/draw.h b/draw.h
index 710087f..6c3d886 100644 (file)
--- a/draw.h
+++ b/draw.h
@@ -33,3 +33,4 @@ extern void loadcolors(Display *dpy, int screen, Brush *b,
 extern void loadfont(Display *dpy, Fnt *font, const char *fontstr);
 extern unsigned int textwidth_l(Fnt *font, char *text, unsigned int len);
 extern unsigned int textwidth(Fnt *font, char *text);
 extern void loadfont(Display *dpy, Fnt *font, const char *fontstr);
 extern unsigned int textwidth_l(Fnt *font, char *text, unsigned int len);
 extern unsigned int textwidth(Fnt *font, char *text);
+extern unsigned int labelheight(Fnt *font);
diff --git a/event.c b/event.c
new file mode 100644 (file)
index 0000000..d6977d3
--- /dev/null
+++ b/event.c
@@ -0,0 +1,264 @@
+/*
+ * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <X11/keysym.h>
+
+#include "wm.h"
+
+/* local functions */
+static void configurerequest(XEvent *e);
+static void destroynotify(XEvent *e);
+static void enternotify(XEvent *e);
+static void leavenotify(XEvent *e);
+static void expose(XEvent *e);
+static void keypress(XEvent *e);
+static void keymapnotify(XEvent *e);
+static void maprequest(XEvent *e);
+static void propertynotify(XEvent *e);
+static void unmapnotify(XEvent *e);
+
+void (*handler[LASTEvent]) (XEvent *) = {
+       [ConfigureRequest] = configurerequest,
+       [DestroyNotify] = destroynotify,
+       [EnterNotify] = enternotify,
+       [LeaveNotify] = leavenotify,
+       [Expose] = expose,
+       [KeyPress] = keypress,
+       [KeymapNotify] = keymapnotify,
+       [MapRequest] = maprequest,
+       [PropertyNotify] = propertynotify,
+       [UnmapNotify] = unmapnotify
+};
+
+unsigned int
+flush_masked_events(long even_mask)
+{
+       XEvent ev;
+       unsigned int n = 0;
+       while(XCheckMaskEvent(dpy, even_mask, &ev)) n++;
+       return n;
+}
+
+static void
+configurerequest(XEvent *e)
+{
+#if 0
+       XConfigureRequestEvent *ev = &e->xconfigurerequest;
+       XWindowChanges wc;
+       XRectangle *frect;
+       Client *c;
+
+       c = client_of_win(ev->window);
+       ev->value_mask &= ~CWSibling;
+       if(c) {
+               gravitate_client(c, True);
+
+               if(ev->value_mask & CWX)
+                       c->rect.x = ev->x;
+               if(ev->value_mask & CWY)
+                       c->rect.y = ev->y;
+               if(ev->value_mask & CWWidth)
+                       c->rect.width = ev->width;
+               if(ev->value_mask & CWHeight)
+                       c->rect.height = ev->height;
+               if(ev->value_mask & CWBorderWidth)
+                       c->border = ev->border_width;
+
+               gravitate_client(c, False);
+
+               if(c->frame) {
+                       if(c->sel->area->floating)
+                               frect=&c->sel->rect;
+                       else
+                               frect=&c->sel->revert;
+
+                       if(c->rect.width >= screen->rect.width && c->rect.height >= screen->rect.height) {
+                               frect->y = wc.y = -height_of_bar();
+                               frect->x = wc.x = -def.border;
+                       }
+                       else {
+                               frect->y = wc.y = c->rect.y - height_of_bar();
+                               frect->x = wc.x = c->rect.x - def.border;
+                       }
+                       frect->width = wc.width = c->rect.width + 2 * def.border;
+                       frect->height = wc.height = c->rect.height + def.border
+                               + height_of_bar();
+                       wc.border_width = 1;
+                       wc.sibling = None;
+                       wc.stack_mode = ev->detail;
+                       if(c->sel->area->view != screen->sel)
+                               wc.x += 2 * screen->rect.width;
+                       if(c->sel->area->floating) {
+                               XConfigureWindow(dpy, c->framewin, ev->value_mask, &wc);
+                               configure_client(c);
+                       }
+               }
+       }
+
+       wc.x = ev->x;
+       wc.y = ev->y;
+       wc.width = ev->width;
+       wc.height = ev->height;
+
+       if(c && c->frame) {
+               wc.x = def.border;
+               wc.y = height_of_bar();
+               wc.width = c->sel->rect.width - 2 * def.border;
+               wc.height = c->sel->rect.height - def.border - height_of_bar();
+       }
+
+       wc.border_width = 0;
+       wc.sibling = None;
+       wc.stack_mode = Above;
+       ev->value_mask &= ~CWStackMode;
+       ev->value_mask |= CWBorderWidth;
+       XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
+
+       XFlush(dpy);
+#endif
+}
+
+static void
+destroynotify(XEvent *e)
+{
+#if 0
+       Client *c;
+       XDestroyWindowEvent *ev = &e->xdestroywindow;
+
+       if((c = client_of_win(ev->window)))
+               destroy_client(c);
+#endif
+}
+
+static void
+enternotify(XEvent *e)
+{
+#if 0
+       XCrossingEvent *ev = &e->xcrossing;
+       Client *c;
+
+       if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
+               return;
+
+       if((c = client_of_win(ev->window))) {
+               Frame *f = c->sel;
+               Area *a = f->area;
+               if(a->mode == Colmax)
+                       c = a->sel->client;
+               focus(c, False);
+       }
+       else if(ev->window == root) {
+               sel_screen = True;
+               draw_frames();
+       }
+#endif
+}
+
+static void
+leavenotify(XEvent *e)
+{
+       XCrossingEvent *ev = &e->xcrossing;
+
+       if((ev->window == root) && !ev->same_screen) {
+               sel_screen = True;
+               /*draw_frames();*/
+       }
+}
+
+static void
+expose(XEvent *e)
+{
+       XExposeEvent *ev = &e->xexpose;
+
+       if(ev->count == 0) {
+               if(ev->window == barwin)
+                       draw_bar();
+       }
+}
+
+static void
+keypress(XEvent *e)
+{
+#if 0
+       XKeyEvent *ev = &e->xkey;
+       KeySym k = 0;
+       char buf[32];
+       int n;
+       static Frame *f;
+
+
+       ev->state &= valid_mask;
+       if((f = frame_of_win(ev->window))) {
+               buf[0] = 0;
+               n = XLookupString(ev, buf, sizeof(buf), &k, 0);
+               if(IsFunctionKey(k) || IsKeypadKey(k) || IsMiscFunctionKey(k)
+                               || IsPFKey(k) || IsPrivateKeypadKey(k))
+                       return;
+               buf[n] = 0;
+               blitz_kpress_input(&f->tagbar, ev->state, k, buf);
+       }
+       else
+               key(root, ev->state, (KeyCode) ev->keycode);
+#endif
+}
+
+static void
+keymapnotify(XEvent *e)
+{
+#if 0
+       update_keys();
+#endif
+}
+
+static void
+maprequest(XEvent *e)
+{
+#if 0
+       XMapRequestEvent *ev = &e->xmaprequest;
+       static XWindowAttributes wa;
+
+       if(!XGetWindowAttributes(dpy, ev->window, &wa))
+               return;
+
+       if(wa.override_redirect) {
+               XSelectInput(dpy, ev->window,
+                               (StructureNotifyMask | PropertyChangeMask));
+               return;
+       }
+
+       if(!client_of_win(ev->window))
+               manage_client(create_client(ev->window, &wa));
+#endif
+}
+
+static void
+propertynotify(XEvent *e)
+{
+#if 0
+       XPropertyEvent *ev = &e->xproperty;
+       Client *c;
+
+       if(ev->state == PropertyDelete)
+               return; /* ignore */
+
+       if((c = client_of_win(ev->window)))
+               prop_client(c, ev);
+#endif
+}
+
+static void
+unmapnotify(XEvent *e)
+{
+#if 0
+       Client *c;
+       XUnmapEvent *ev = &e->xunmap;
+
+       if((c = client_of_win(ev->window)))
+               destroy_client(c);
+#endif
+}
diff --git a/menu.c b/menu.c
index b4e08d4..7c84305 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -53,7 +53,7 @@ static const int seek = 30;           /* 30px */
 
 static Brush brush = {0};
 
 
 static Brush brush = {0};
 
-static void draw_menu(void);
+static void draw_menu();
 static void kpress(XKeyEvent * e);
 
 static char version[] = "gridmenu - " VERSION ", (C)opyright MMVI Anselm R. Garbe\n";
 static void kpress(XKeyEvent * e);
 
 static char version[] = "gridmenu - " VERSION ", (C)opyright MMVI Anselm R. Garbe\n";
@@ -397,11 +397,10 @@ main(int argc, char *argv[])
 
        wa.override_redirect = 1;
        wa.background_pixmap = ParentRelative;
 
        wa.override_redirect = 1;
        wa.background_pixmap = ParentRelative;
-       wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask
-               | SubstructureRedirectMask | SubstructureNotifyMask;
+       wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask;
 
        rect.width = DisplayWidth(dpy, screen);
 
        rect.width = DisplayWidth(dpy, screen);
-       rect.height = brush.font.height + 4;
+       rect.height = labelheight(&brush.font);
        rect.y = DisplayHeight(dpy, screen) - rect.height;
        rect.x = 0;
 
        rect.y = DisplayHeight(dpy, screen) - rect.height;
        rect.x = 0;
 
@@ -413,7 +412,7 @@ main(int argc, char *argv[])
        XFlush(dpy);
 
        /* pixmap */
        XFlush(dpy);
 
        /* pixmap */
-       brush.gc = XCreateGC(dpy, win, 0, 0);
+       brush.gc = XCreateGC(dpy, root, 0, 0);
        brush.drawable = XCreatePixmap(dpy, win, rect.width, rect.height,
                        DefaultDepth(dpy, screen));
        XFlush(dpy);
        brush.drawable = XCreatePixmap(dpy, win, rect.width, rect.height,
                        DefaultDepth(dpy, screen));
        XFlush(dpy);
diff --git a/util.c b/util.c
index 99842e9..435069f 100644 (file)
--- a/util.c
+++ b/util.c
@@ -7,6 +7,11 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "util.h"
 
 void
 error(char *errstr, ...) {
 
 void
 error(char *errstr, ...) {
@@ -75,3 +80,21 @@ swap(void **p1, void **p2)
        *p1 = *p2;
        *p2 = tmp;
 }
        *p1 = *p2;
        *p2 = tmp;
 }
+
+void
+spawn(Display *dpy, const char *shell, const char *cmd)
+{
+       if(!cmd || !shell)
+               return;
+       if(fork() == 0) {
+               if(fork() == 0) {
+                       if(dpy)
+                               close(ConnectionNumber(dpy));
+                       execl(shell, shell, "-c", cmd, (const char *)0);
+                       fprintf(stderr, "gridwm: execl %s", shell);
+                       perror(" failed");
+               }
+               exit (0);
+       }
+       wait(0);
+}
diff --git a/util.h b/util.h
index 8ba444b..cac3df0 100644 (file)
--- a/util.h
+++ b/util.h
@@ -2,6 +2,7 @@
  * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
  * See LICENSE file for license details.
  */
  * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
  * See LICENSE file for license details.
  */
+#include <X11/Xlib.h>
 
 extern void error(char *errstr, ...);
 extern void *emallocz(unsigned int size);
 
 extern void error(char *errstr, ...);
 extern void *emallocz(unsigned int size);
@@ -12,5 +13,6 @@ extern char *estrdup(const char *str);
                if(!(a)) \
                        failed_assert(#a, __FILE__, __LINE__); \
        } while (0)
                if(!(a)) \
                        failed_assert(#a, __FILE__, __LINE__); \
        } while (0)
-void failed_assert(char *a, char *file, int line);
-void swap(void **p1, void **p2);
+extern void failed_assert(char *a, char *file, int line);
+extern void swap(void **p1, void **p2);
+extern void spawn(Display *dpy, const char *shell, const char *cmd);
diff --git a/wm.c b/wm.c
index c8bb0a4..b8b3053 100644 (file)
--- a/wm.c
+++ b/wm.c
 
 /* X structs */
 Display *dpy;
 
 /* X structs */
 Display *dpy;
-Window root;
-XRectangle rect;
-Pixmap pmap;
-Atom wm_atom[WMLast];
-Atom net_atom[NetLast];
+Window root, barwin;
+Atom wm_atom[WMLast], net_atom[NetLast];
 Cursor cursor[CurLast];
 Cursor cursor[CurLast];
+XRectangle rect, barrect;
+Bool running = True;
 
 
+char *bartext, *shell;
 int screen, sel_screen;
 int screen, sel_screen;
-unsigned int kmask, numlock_mask;
+unsigned int lock_mask, numlock_mask;
 
 /* draw structs */
 Brush brush = {0};
 
 /* draw structs */
 Brush brush = {0};
@@ -166,7 +166,7 @@ init_lock_keys()
        }
        XFreeModifiermap(modmap);
 
        }
        XFreeModifiermap(modmap);
 
-       kmask = 255 & ~(numlock_mask | LockMask);
+       lock_mask = 255 & ~(numlock_mask | LockMask);
 }
 
 static void
 }
 
 static void
@@ -187,6 +187,7 @@ main(int argc, char *argv[])
        XSetWindowAttributes wa;
        unsigned int mask;
        Window w;
        XSetWindowAttributes wa;
        unsigned int mask;
        Window w;
+       XEvent ev;
 
        /* command line args */
        for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
 
        /* command line args */
        for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
@@ -218,6 +219,9 @@ main(int argc, char *argv[])
        if(other_wm_running)
                error("gridwm: another window manager is already running\n");
 
        if(other_wm_running)
                error("gridwm: another window manager is already running\n");
 
+       if(!(shell = getenv("SHELL")))
+               shell = "/bin/sh";
+
        rect.x = rect.y = 0;
        rect.width = DisplayWidth(dpy, screen);
        rect.height = DisplayHeight(dpy, screen);
        rect.x = rect.y = 0;
        rect.width = DisplayWidth(dpy, screen);
        rect.height = DisplayHeight(dpy, screen);
@@ -244,19 +248,42 @@ main(int argc, char *argv[])
 
        init_lock_keys();
 
 
        init_lock_keys();
 
-       pmap = XCreatePixmap(dpy, root, rect.width, rect.height,
+       brush.drawable = XCreatePixmap(dpy, root, rect.width, rect.height,
                        DefaultDepth(dpy, screen));
                        DefaultDepth(dpy, screen));
-
-       wa.event_mask = SubstructureRedirectMask | EnterWindowMask | LeaveWindowMask;
-       wa.cursor = cursor[CurNormal];
-       XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
+       brush.gc = XCreateGC(dpy, root, 0, 0);
 
        /* style */
        loadcolors(dpy, screen, &brush, BGCOLOR, FGCOLOR, BORDERCOLOR);
        loadfont(dpy, &brush.font, FONT);
 
 
        /* style */
        loadcolors(dpy, screen, &brush, BGCOLOR, FGCOLOR, BORDERCOLOR);
        loadfont(dpy, &brush.font, FONT);
 
+       wa.override_redirect = 1;
+       wa.background_pixmap = ParentRelative;
+       wa.event_mask = ExposureMask;
+
+       barrect = rect;
+       barrect.height = labelheight(&brush.font);
+       barrect.y = rect.height - barrect.height;
+       barwin = XCreateWindow(dpy, root, barrect.x, barrect.y,
+                       barrect.width, barrect.height, 0, DefaultDepth(dpy, screen),
+                       CopyFromParent, DefaultVisual(dpy, screen),
+                       CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
+       bartext = 0;
+       XDefineCursor(dpy, barwin, cursor[CurNormal]);
+       XMapRaised(dpy, barwin);
+       draw_bar();
+
+       wa.event_mask = SubstructureRedirectMask | EnterWindowMask | LeaveWindowMask;
+       wa.cursor = cursor[CurNormal];
+       XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
+
        scan_wins();
 
        scan_wins();
 
+       while(running) {
+               XNextEvent(dpy, &ev);
+               if(handler[ev.type])
+                       (handler[ev.type]) (&ev); /* call handler */
+       }
+
        cleanup();
        XCloseDisplay(dpy);
 
        cleanup();
        XCloseDisplay(dpy);
 
diff --git a/wm.h b/wm.h
index 6bf0d5e..038078f 100644 (file)
--- a/wm.h
+++ b/wm.h
@@ -9,16 +9,14 @@
 
 #include <X11/Xutil.h>
 
 
 #include <X11/Xutil.h>
 
-/* WM atoms */
+/* atoms */
 enum { WMState, WMProtocols, WMDelete, WMLast };
 enum { WMState, WMProtocols, WMDelete, WMLast };
-
-/* NET atoms */
 enum { NetSupported, NetWMName, NetLast };
 
 enum { NetSupported, NetWMName, NetLast };
 
-/* Cursor */
+/* cursor */
 enum { CurNormal, CurResize, CurMove, CurInput, CurLast };
 
 enum { CurNormal, CurResize, CurMove, CurInput, CurLast };
 
-/* Rects */
+/* rects */
 enum { RFloat, RGrid, RLast };
 
 typedef struct Client Client;
 enum { RFloat, RGrid, RLast };
 
 typedef struct Client Client;
@@ -28,35 +26,45 @@ struct Client {
        Tag *tag;
        char name[256];
        int proto;
        Tag *tag;
        char name[256];
        int proto;
+       unsigned int border;
+       Bool fixedsize;
        Window win;
        Window trans;
        Window title;
        Window win;
        Window trans;
        Window title;
-       GC gc;
        XSizeHints size;
        XRectangle r[RLast];
        Client *next;
        XSizeHints size;
        XRectangle r[RLast];
        Client *next;
-       Client *tnext;
-       Client *tprev;
+       Client *snext;
 };
 
 struct Tag {
        char name[256];
 };
 
 struct Tag {
        char name[256];
-       Client *clients;
-       Client *sel;
+       Client *stack;
        XRectangle r;
        XRectangle r;
+       Tag *next;
+       Tag *cnext;
 };
 
 extern Display *dpy;
 };
 
 extern Display *dpy;
-extern Window root;
-extern XRectangle rect;
-extern Atom wm_atom[WMLast];
-extern Atom net_atom[NetLast];
+extern Window root, barwin;
+extern Atom wm_atom[WMLast], net_atom[NetLast];
 extern Cursor cursor[CurLast];
 extern Cursor cursor[CurLast];
-extern Pixmap pmap;
+extern XRectangle rect, barrect;
+extern Bool running;
+extern void (*handler[LASTEvent]) (XEvent *);
 
 extern int screen, sel_screen;
 
 extern int screen, sel_screen;
-extern unsigned int kmask, numlock_mask;
+extern unsigned int lock_mask, numlock_mask;
+extern char *bartext, *shell;
 
 extern Brush brush;
 
 
 extern Brush brush;
 
+/* bar.c */
+extern void draw_bar();
+
+/* client.c */
+extern Client *create_client(Window w, XWindowAttributes *wa);
+extern void manage(Client *c);
+
 /* wm.c */
 /* wm.c */
+extern int win_proto(Window w);