dwm

my fork of dwm
Index Commits Files Refs README LICENSE
commit 439e15d09f6fa9271d3b49ef97194f0c80ebe161
parent 2de59d0f0927cec656fc4b9f6fc9ea178fb01c1e
Author: Anselm R. Garbe <garbeam@wmii.de>
Date:   Mon, 10 Jul 2006 22:16:48 +0200

added several other stuff

Diffstat:
MMakefile | 4++--
Abar.c | 18++++++++++++++++++
Aclient.c | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mconfig.h | 4++--
Mdraw.c | 6++++++
Mdraw.h | 1+
Aevent.c | 264+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmenu.c | 9++++-----
Mutil.c | 23+++++++++++++++++++++++
Mutil.h | 6++++--
Mwm.c | 51+++++++++++++++++++++++++++++++++++++++------------
Mwm.h | 40++++++++++++++++++++++++----------------
12 files changed, 476 insertions(+), 39 deletions(-)
diff --git a/Makefile b/Makefile
@@ -3,11 +3,11 @@
 
 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}
-MAN = gridwm.1
+MAN1 = gridwm.1 gridmenu.1
 BIN = gridwm gridmenu     
 
 all: config gridwm gridmenu
diff --git a/bar.c 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
@@ -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);
+}
diff --git a/config.h b/config.h
@@ -4,6 +4,6 @@
  */
 
 #define FONT        "-*-terminus-medium-*-*-*-14-*-*-*-*-*-iso10646-*"
-#define FGCOLOR        "#000000"
-#define BGCOLOR        "#ffaa00"
+#define BGCOLOR        "#000000"
+#define FGCOLOR        "#ffaa00"
 #define BORDERCOLOR    "#000000"
diff --git a/draw.c b/draw.c
@@ -162,3 +162,9 @@ loadfont(Display *dpy, Fnt *font, const char *fontstr)
     }
     font->height = font->ascent + font->descent;
 }
+
+unsigned int
+labelheight(Fnt *font)
+{
+    return font->height + 4;
+}
diff --git 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 unsigned int labelheight(Fnt *font);
diff --git a/event.c 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
@@ -53,7 +53,7 @@ static const int seek = 30;		/* 30px */
 
 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";
@@ -397,11 +397,10 @@ main(int argc, char *argv[])
 
     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.height = brush.font.height + 4;
+    rect.height = labelheight(&brush.font);
     rect.y = DisplayHeight(dpy, screen) - rect.height;
     rect.x = 0;
 
@@ -413,7 +412,7 @@ main(int argc, char *argv[])
     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);
diff --git a/util.c b/util.c
@@ -7,6 +7,11 @@
 #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, ...) {
@@ -75,3 +80,21 @@ swap(void **p1, void **p2)
     *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
@@ -2,6 +2,7 @@
  * (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);
@@ -12,5 +13,6 @@ extern char *estrdup(const char *str);
         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
@@ -15,15 +15,15 @@
 
 /* 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];
+XRectangle rect, barrect;
+Bool running = True;
 
+char *bartext, *shell;
 int screen, sel_screen;
-unsigned int kmask, numlock_mask;
+unsigned int lock_mask, numlock_mask;
 
 /* draw structs */
 Brush brush = {0};
@@ -166,7 +166,7 @@ init_lock_keys()
     }
     XFreeModifiermap(modmap);
 
-    kmask = 255 & ~(numlock_mask | LockMask);
+    lock_mask = 255 & ~(numlock_mask | LockMask);
 }
 
 static void
@@ -187,6 +187,7 @@ main(int argc, char *argv[])
     XSetWindowAttributes wa;
     unsigned int mask;
     Window w;
+    XEvent ev;
 
     /* 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(!(shell = getenv("SHELL")))
+        shell = "/bin/sh";
+
     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();
 
-    pmap = XCreatePixmap(dpy, root, rect.width, rect.height,
+    brush.drawable = XCreatePixmap(dpy, root, rect.width, rect.height,
             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);
 
+    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();
 
+    while(running) {
+        XNextEvent(dpy, &ev);
+        if(handler[ev.type])
+            (handler[ev.type]) (&ev); /* call handler */
+    }
+
     cleanup();
     XCloseDisplay(dpy);
 
diff --git a/wm.h b/wm.h
@@ -9,16 +9,14 @@
 
 #include <X11/Xutil.h>
 
-/* WM atoms */
+/* atoms */
 enum { WMState, WMProtocols, WMDelete, WMLast };
-
-/* NET atoms */
 enum { NetSupported, NetWMName, NetLast };
 
-/* Cursor */
+/* cursor */
 enum { CurNormal, CurResize, CurMove, CurInput, CurLast };
 
-/* Rects */
+/* rects */
 enum { RFloat, RGrid, RLast };
 
 typedef struct Client Client;
@@ -28,35 +26,45 @@ struct Client {
     Tag *tag;
     char name[256];
     int proto;
+    unsigned int border;
+    Bool fixedsize;
     Window win;
     Window trans;
     Window title;
-    GC gc;
     XSizeHints size;
     XRectangle r[RLast];
     Client *next;
-    Client *tnext;
-    Client *tprev;
+    Client *snext;
 };
 
 struct Tag {
     char name[256];
-    Client *clients;
-    Client *sel;
+    Client *stack;
     XRectangle r;
+    Tag *next;
+    Tag *cnext;
 };
 
 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 Pixmap pmap;
+extern XRectangle rect, barrect;
+extern Bool running;
+extern void (*handler[LASTEvent]) (XEvent *);
 
 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;
 
+/* bar.c */
+extern void draw_bar();
+
+/* client.c */
+extern Client *create_client(Window w, XWindowAttributes *wa);
+extern void manage(Client *c);
+
 /* wm.c */
+extern int win_proto(Window w);