rearranged several stuff

This commit is contained in:
Anselm R. Garbe 2006-07-15 16:30:50 +02:00
parent c0705eeb65
commit dba23062ba
10 changed files with 442 additions and 444 deletions

View file

@ -3,7 +3,7 @@
include config.mk include config.mk
SRC = client.c draw.c event.c key.c main.c screen.c util.c SRC = client.c draw.c event.c main.c tag.c util.c
OBJ = ${SRC:.c=.o} OBJ = ${SRC:.c=.o}
MAN1 = dwm.1 MAN1 = dwm.1
BIN = dwm BIN = dwm

145
client.c
View file

@ -11,18 +11,6 @@
#include "dwm.h" #include "dwm.h"
static Rule rule[] = {
/* class instance tags floating */
{ "Firefox-bin", "Gecko", { [Twww] = "www" }, False },
};
Client *
getnext(Client *c)
{
for(; c && !c->tags[tsel]; c = c->next);
return c;
}
void void
ban(Client *c) ban(Client *c)
{ {
@ -31,7 +19,7 @@ ban(Client *c)
} }
static void static void
resize_title(Client *c) resizetitle(Client *c)
{ {
int i; int i;
@ -72,7 +60,7 @@ settitle(Client *c)
} }
} }
XFree(name.value); XFree(name.value);
resize_title(c); resizetitle(c);
} }
void void
@ -143,42 +131,6 @@ focus(Client *c)
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
} }
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) {
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)))
{
for(j = 0; j < TLast; j++)
c->tags[j] = rule[i].tags[j];
c->floating = rule[i].floating;
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 void
manage(Window w, XWindowAttributes *wa) manage(Window w, XWindowAttributes *wa)
{ {
@ -196,7 +148,7 @@ manage(Window w, XWindowAttributes *wa)
c->h = wa->height; c->h = wa->height;
c->th = bh; c->th = bh;
c->border = 1; c->border = 1;
c->proto = proto(c->win); c->proto = getproto(c->win);
setsize(c); setsize(c);
XSelectInput(dpy, c->win, XSelectInput(dpy, c->win,
StructureNotifyMask | PropertyChangeMask | EnterWindowMask); StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
@ -211,7 +163,7 @@ manage(Window w, XWindowAttributes *wa)
CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa); CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
settitle(c); settitle(c);
init_tags(c); settags(c);
for(l = &clients; *l; l = &(*l)->next); for(l = &clients; *l; l = &(*l)->next);
c->next = *l; /* *l == nil */ c->next = *l; /* *l == nil */
@ -224,8 +176,8 @@ manage(Window w, XWindowAttributes *wa)
XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask, XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask,
GrabModeAsync, GrabModeSync, None, None); GrabModeAsync, GrabModeSync, None, None);
if(!c->floating) if(!c->dofloat)
c->floating = trans c->dofloat = trans
|| ((c->maxw == c->minw) && (c->maxh == c->minh)); || ((c->maxw == c->minw) && (c->maxh == c->minh));
arrange(NULL); arrange(NULL);
@ -321,7 +273,7 @@ resize(Client *c, Bool inc)
c->w = c->maxw; c->w = c->maxw;
if(c->maxh && c->h > c->maxh) if(c->maxh && c->h > c->maxh)
c->h = c->maxh; c->h = c->maxh;
resize_title(c); resizetitle(c);
XSetWindowBorderWidth(dpy, c->win, 1); XSetWindowBorderWidth(dpy, c->win, 1);
XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
e.type = ConfigureNotify; e.type = ConfigureNotify;
@ -339,7 +291,7 @@ resize(Client *c, Bool inc)
} }
static int static int
dummy_xerror(Display *dsply, XErrorEvent *err) xerrordummy(Display *dsply, XErrorEvent *ee)
{ {
return 0; return 0;
} }
@ -350,7 +302,7 @@ unmanage(Client *c)
Client **l; Client **l;
XGrabServer(dpy); XGrabServer(dpy);
XSetErrorHandler(dummy_xerror); XSetErrorHandler(xerrordummy);
XUngrabButton(dpy, AnyButton, AnyModifier, c->win); XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
XDestroyWindow(dpy, c->title); XDestroyWindow(dpy, c->title);
@ -374,7 +326,7 @@ unmanage(Client *c)
} }
Client * Client *
gettitle(Window w) getctitle(Window w)
{ {
Client *c; Client *c;
for(c = clients; c; c = c->next) for(c = clients; c; c = c->next)
@ -392,3 +344,80 @@ getclient(Window w)
return c; return c;
return NULL; return NULL;
} }
void
zoom(Arg *arg)
{
Client **l, *c;
if(!sel)
return;
if(sel == getnext(clients) && sel->next) {
if((c = getnext(sel->next)))
sel = c;
}
for(l = &clients; *l && *l != sel; l = &(*l)->next);
*l = sel->next;
sel->next = clients; /* pop */
clients = sel;
arrange(NULL);
focus(sel);
}
void
maximize(Arg *arg)
{
if(!sel)
return;
sel->x = sx;
sel->y = sy + bh;
sel->w = sw - 2 * sel->border;
sel->h = sh - 2 * sel->border - bh;
higher(sel);
resize(sel, False);
}
void
focusprev(Arg *arg)
{
Client *c;
if(!sel)
return;
if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) {
higher(c);
focus(c);
}
}
void
focusnext(Arg *arg)
{
Client *c;
if(!sel)
return;
if(!(c = getnext(sel->next)))
c = getnext(clients);
if(c) {
higher(c);
c->revert = sel;
focus(c);
}
}
void
killclient(Arg *arg)
{
if(!sel)
return;
if(sel->proto & WM_PROTOCOL_DELWIN)
sendevent(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
else
XKillClient(dpy, sel->win);
}

37
draw.c
View file

@ -10,34 +10,43 @@
#include "dwm.h" #include "dwm.h"
void
drawall()
{
Client *c;
for(c = clients; c; c = getnext(c->next))
drawtitle(c);
drawstatus();
}
void void
drawstatus() drawstatus()
{ {
int i; int i;
Bool istile = arrange == dotile;
dc.x = dc.y = 0; dc.x = dc.y = 0;
dc.w = bw; dc.w = bw;
drawtext(NULL, False, False); drawtext(NULL, !istile, False);
if(arrange == floating) { dc.w = 0;
dc.w = textw("~");
drawtext("~", False, False);
}
else
dc.w = 0;
for(i = 0; i < TLast; i++) { for(i = 0; i < TLast; i++) {
dc.x += dc.w; dc.x += dc.w;
dc.w = textw(tags[i]); dc.w = textw(tags[i]);
drawtext(tags[i], i == tsel, True); if(istile)
drawtext(tags[i], (i == tsel), True);
else
drawtext(tags[i], (i != tsel), True);
} }
if(sel) { if(sel) {
dc.x += dc.w; dc.x += dc.w;
dc.w = textw(sel->name); dc.w = textw(sel->name);
drawtext(sel->name, True, True); drawtext(sel->name, istile, True);
} }
dc.w = textw(stext); dc.w = textw(stext);
dc.x = bx + bw - dc.w; dc.x = bx + bw - dc.w;
drawtext(stext, False, False); drawtext(stext, !istile, False);
XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, bw, bh, 0, 0); XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, bw, bh, 0, 0);
XFlush(dpy); XFlush(dpy);
@ -47,6 +56,8 @@ void
drawtitle(Client *c) drawtitle(Client *c)
{ {
int i; int i;
Bool istile = arrange == dotile;
if(c == sel) { if(c == sel) {
drawstatus(); drawstatus();
XUnmapWindow(dpy, c->title); XUnmapWindow(dpy, c->title);
@ -64,12 +75,12 @@ drawtitle(Client *c)
if(c->tags[i]) { if(c->tags[i]) {
dc.x += dc.w; dc.x += dc.w;
dc.w = textw(c->tags[i]); dc.w = textw(c->tags[i]);
drawtext(c->tags[i], False, True); drawtext(c->tags[i], !istile, True);
} }
} }
dc.x += dc.w; dc.x += dc.w;
dc.w = textw(c->name); dc.w = textw(c->name);
drawtext(c->name, False, True); drawtext(c->name, !istile, True);
XCopyArea(dpy, dc.drawable, c->title, dc.gc, XCopyArea(dpy, dc.drawable, c->title, dc.gc,
0, 0, c->tw, c->th, 0, 0); 0, 0, c->tw, c->th, 0, 0);
XFlush(dpy); XFlush(dpy);
@ -215,7 +226,7 @@ setfont(const char *fontstr)
if (!dc.font.xfont) if (!dc.font.xfont)
dc.font.xfont = XLoadQueryFont(dpy, "fixed"); dc.font.xfont = XLoadQueryFont(dpy, "fixed");
if (!dc.font.xfont) if (!dc.font.xfont)
error("error, cannot init 'fixed' font\n"); eprint("error, cannot init 'fixed' font\n");
dc.font.ascent = dc.font.xfont->ascent; dc.font.ascent = dc.font.xfont->ascent;
dc.font.descent = dc.font.xfont->descent; dc.font.descent = dc.font.xfont->descent;
} }

36
dwm.h
View file

@ -66,7 +66,7 @@ struct Client {
int grav; int grav;
unsigned int border; unsigned int border;
long flags; long flags;
Bool floating; Bool dofloat;
Window win; Window win;
Window title; Window title;
Client *next; Client *next;
@ -77,7 +77,7 @@ struct Rule {
const char *class; const char *class;
const char *instance; const char *instance;
char *tags[TLast]; char *tags[TLast];
Bool floating; Bool dofloat;
}; };
struct Key { struct Key {
@ -103,6 +103,7 @@ extern DC dc;
extern Client *clients, *sel; extern Client *clients, *sel;
/* client.c */ /* client.c */
extern void ban(Client *c);
extern void manage(Window w, XWindowAttributes *wa); extern void manage(Window w, XWindowAttributes *wa);
extern void unmanage(Client *c); extern void unmanage(Client *c);
extern Client *getclient(Window w); extern Client *getclient(Window w);
@ -110,14 +111,18 @@ extern void focus(Client *c);
extern void settitle(Client *c); extern void settitle(Client *c);
extern void resize(Client *c, Bool inc); extern void resize(Client *c, Bool inc);
extern void setsize(Client *c); extern void setsize(Client *c);
extern Client *gettitle(Window w); extern Client *getctitle(Window w);
extern void higher(Client *c); extern void higher(Client *c);
extern void lower(Client *c); extern void lower(Client *c);
extern void gravitate(Client *c, Bool invert); extern void gravitate(Client *c, Bool invert);
extern void ban(Client *c); extern void zoom(Arg *arg);
extern Client *getnext(Client *c); extern void maximize(Arg *arg);
extern void focusprev(Arg *arg);
extern void focusnext(Arg *arg);
extern void killclient(Arg *arg);
/* draw.c */ /* draw.c */
extern void drawall();
extern void drawstatus(); extern void drawstatus();
extern void drawtitle(Client *c); extern void drawtitle(Client *c);
extern void drawtext(const char *text, Bool invert, Bool border); extern void drawtext(const char *text, Bool invert, Bool border);
@ -127,22 +132,25 @@ extern unsigned int textnw(char *text, unsigned int len);
extern unsigned int textw(char *text); extern unsigned int textw(char *text);
extern unsigned int texth(void); extern unsigned int texth(void);
/* key.c */ /* event.c */
extern void grabkeys(); extern void grabkeys();
extern void keypress(XEvent *e);
/* main.c */ /* main.c */
extern int xerror(Display *dsply, XErrorEvent *e);
extern void sendevent(Window w, Atom a, long value);
extern int proto(Window w);
extern void quit(Arg *arg); extern void quit(Arg *arg);
extern int xerror(Display *dsply, XErrorEvent *ee);
extern void sendevent(Window w, Atom a, long value);
extern int getproto(Window w);
/* screen.c */ /* tag.c */
extern void floating(Arg *arg); extern Client *getnext(Client *c);
extern void tiling(Arg *arg); extern void settags(Client *c);
extern void dofloat(Arg *arg);
extern void dotile(Arg *arg);
extern void view(Arg *arg); extern void view(Arg *arg);
extern void appendtag(Arg *arg);
extern void replacetag(Arg *arg);
/* util.c */ /* util.c */
extern void error(const char *errstr, ...); extern void eprint(const char *errstr, ...);
extern void *emallocz(unsigned int size); extern void *emallocz(unsigned int size);
extern void spawn(Arg *arg); extern void spawn(Arg *arg);

89
event.c
View file

@ -16,6 +16,44 @@
#define ButtonMask (ButtonPressMask | ButtonReleaseMask) #define ButtonMask (ButtonPressMask | ButtonReleaseMask)
#define MouseMask (ButtonMask | PointerMotionMask) #define MouseMask (ButtonMask | PointerMotionMask)
/********** CUSTOMIZE **********/
const char *term[] = {
"urxvtc", "-tr", "+sb", "-bg", "black", "-fg", "white", "-fn",
"-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*",NULL
};
const char *browse[] = { "firefox", NULL };
const char *xlock[] = { "xlock", NULL };
Key key[] = {
/* modifier key function arguments */
{ Mod1Mask, XK_Return, zoom, { 0 } },
{ Mod1Mask, XK_k, focusprev, { 0 } },
{ Mod1Mask, XK_j, focusnext, { 0 } },
{ Mod1Mask, XK_m, maximize, { 0 } },
{ Mod1Mask, XK_0, view, { .i = Tscratch } },
{ Mod1Mask, XK_1, view, { .i = Tdev } },
{ Mod1Mask, XK_2, view, { .i = Twww } },
{ Mod1Mask, XK_3, view, { .i = Twork } },
{ Mod1Mask, XK_space, dotile, { 0 } },
{ Mod1Mask|ShiftMask, XK_space, dofloat, { 0 } },
{ Mod1Mask|ShiftMask, XK_0, replacetag, { .i = Tscratch } },
{ Mod1Mask|ShiftMask, XK_1, replacetag, { .i = Tdev } },
{ Mod1Mask|ShiftMask, XK_2, replacetag, { .i = Twww } },
{ Mod1Mask|ShiftMask, XK_3, replacetag, { .i = Twork } },
{ Mod1Mask|ShiftMask, XK_c, killclient, { 0 } },
{ Mod1Mask|ShiftMask, XK_q, quit, { 0 } },
{ Mod1Mask|ShiftMask, XK_Return, spawn, { .argv = term } },
{ Mod1Mask|ShiftMask, XK_w, spawn, { .argv = browse } },
{ Mod1Mask|ShiftMask, XK_l, spawn, { .argv = xlock } },
{ ControlMask, XK_0, appendtag, { .i = Tscratch } },
{ ControlMask, XK_1, appendtag, { .i = Tdev } },
{ ControlMask, XK_2, appendtag, { .i = Twww } },
{ ControlMask, XK_3, appendtag, { .i = Twork } },
};
/********** CUSTOMIZE **********/
/* local functions */ /* local functions */
static void buttonpress(XEvent *e); static void buttonpress(XEvent *e);
static void configurerequest(XEvent *e); static void configurerequest(XEvent *e);
@ -23,6 +61,7 @@ static void destroynotify(XEvent *e);
static void enternotify(XEvent *e); static void enternotify(XEvent *e);
static void leavenotify(XEvent *e); static void leavenotify(XEvent *e);
static void expose(XEvent *e); static void expose(XEvent *e);
static void keypress(XEvent *e);
static void maprequest(XEvent *e); static void maprequest(XEvent *e);
static void propertynotify(XEvent *e); static void propertynotify(XEvent *e);
static void unmapnotify(XEvent *e); static void unmapnotify(XEvent *e);
@ -40,8 +79,40 @@ void (*handler[LASTEvent]) (XEvent *) = {
[UnmapNotify] = unmapnotify [UnmapNotify] = unmapnotify
}; };
void
grabkeys()
{
static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
unsigned int i;
KeyCode code;
for(i = 0; i < len; i++) {
code = XKeysymToKeycode(dpy, key[i].keysym);
XUngrabKey(dpy, code, key[i].mod, root);
XGrabKey(dpy, code, key[i].mod, root, True,
GrabModeAsync, GrabModeAsync);
}
}
static void static void
mresize(Client *c) keypress(XEvent *e)
{
XKeyEvent *ev = &e->xkey;
static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
unsigned int i;
KeySym keysym;
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
for(i = 0; i < len; i++)
if((keysym == key[i].keysym) && (key[i].mod == ev->state)) {
if(key[i].func)
key[i].func(&key[i].arg);
return;
}
}
static void
resizemouse(Client *c)
{ {
XEvent ev; XEvent ev;
int ocx, ocy; int ocx, ocy;
@ -75,7 +146,7 @@ mresize(Client *c)
} }
static void static void
mmove(Client *c) movemouse(Client *c)
{ {
XEvent ev; XEvent ev;
int x1, y1, ocx, ocy, di; int x1, y1, ocx, ocy, di;
@ -117,7 +188,7 @@ buttonpress(XEvent *e)
Client *c; Client *c;
if(barwin == ev->window) { if(barwin == ev->window) {
x = (arrange == floating) ? textw("~") : 0; x = (arrange == dofloat) ? textw("~") : 0;
for(a.i = 0; a.i < TLast; a.i++) { for(a.i = 0; a.i < TLast; a.i++) {
x += textw(tags[a.i]); x += textw(tags[a.i]);
if(ev->x < x) { if(ev->x < x) {
@ -127,20 +198,20 @@ buttonpress(XEvent *e)
} }
} }
else if((c = getclient(ev->window))) { else if((c = getclient(ev->window))) {
if(arrange == tiling && !c->floating) if(arrange == dotile && !c->dofloat)
return; return;
higher(c); higher(c);
switch(ev->button) { switch(ev->button) {
default: default:
break; break;
case Button1: case Button1:
mmove(c); movemouse(c);
break; break;
case Button2: case Button2:
lower(c); lower(c);
break; break;
case Button3: case Button3:
mresize(c); resizemouse(c);
break; break;
} }
} }
@ -226,7 +297,7 @@ expose(XEvent *e)
if(ev->count == 0) { if(ev->count == 0) {
if(barwin == ev->window) if(barwin == ev->window)
drawstatus(); drawstatus();
else if((c = gettitle(ev->window))) else if((c = getctitle(ev->window)))
drawtitle(c); drawtitle(c);
} }
} }
@ -262,14 +333,14 @@ propertynotify(XEvent *e)
if((c = getclient(ev->window))) { if((c = getclient(ev->window))) {
if(ev->atom == wm_atom[WMProtocols]) { if(ev->atom == wm_atom[WMProtocols]) {
c->proto = proto(c->win); c->proto = getproto(c->win);
return; return;
} }
switch (ev->atom) { switch (ev->atom) {
default: break; default: break;
case XA_WM_TRANSIENT_FOR: case XA_WM_TRANSIENT_FOR:
XGetTransientForHint(dpy, c->win, &trans); XGetTransientForHint(dpy, c->win, &trans);
if(!c->floating && (c->floating = (trans != 0))) if(!c->dofloat && (c->dofloat = (trans != 0)))
arrange(NULL); arrange(NULL);
break; break;
case XA_WM_NORMAL_HINTS: case XA_WM_NORMAL_HINTS:

192
key.c
View file

@ -1,192 +0,0 @@
/*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
#include "dwm.h"
static void ckill(Arg *arg);
static void nextc(Arg *arg);
static void prevc(Arg *arg);
static void max(Arg *arg);
static void ttrunc(Arg *arg);
static void tappend(Arg *arg);
static void zoom(Arg *arg);
/********** CUSTOMIZE **********/
const char *term[] = {
"urxvtc", "-tr", "+sb", "-bg", "black", "-fg", "white", "-fn",
"-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*",NULL
};
const char *browse[] = { "firefox", NULL };
const char *xlock[] = { "xlock", NULL };
Key key[] = {
/* modifier key function arguments */
{ Mod1Mask, XK_Return, zoom, { 0 } },
{ Mod1Mask, XK_k, prevc, { 0 } },
{ Mod1Mask, XK_j, nextc, { 0 } },
{ Mod1Mask, XK_m, max, { 0 } },
{ Mod1Mask, XK_0, view, { .i = Tscratch } },
{ Mod1Mask, XK_1, view, { .i = Tdev } },
{ Mod1Mask, XK_2, view, { .i = Twww } },
{ Mod1Mask, XK_3, view, { .i = Twork } },
{ Mod1Mask, XK_space, tiling, { 0 } },
{ Mod1Mask|ShiftMask, XK_space, floating, { 0 } },
{ Mod1Mask|ShiftMask, XK_0, ttrunc, { .i = Tscratch } },
{ Mod1Mask|ShiftMask, XK_1, ttrunc, { .i = Tdev } },
{ Mod1Mask|ShiftMask, XK_2, ttrunc, { .i = Twww } },
{ Mod1Mask|ShiftMask, XK_3, ttrunc, { .i = Twork } },
{ Mod1Mask|ShiftMask, XK_c, ckill, { 0 } },
{ Mod1Mask|ShiftMask, XK_q, quit, { 0 } },
{ Mod1Mask|ShiftMask, XK_Return, spawn, { .argv = term } },
{ Mod1Mask|ShiftMask, XK_w, spawn, { .argv = browse } },
{ Mod1Mask|ShiftMask, XK_l, spawn, { .argv = xlock } },
{ ControlMask, XK_0, tappend, { .i = Tscratch } },
{ ControlMask, XK_1, tappend, { .i = Tdev } },
{ ControlMask, XK_2, tappend, { .i = Twww } },
{ ControlMask, XK_3, tappend, { .i = Twork } },
};
/********** CUSTOMIZE **********/
void
grabkeys()
{
static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
unsigned int i;
KeyCode code;
for(i = 0; i < len; i++) {
code = XKeysymToKeycode(dpy, key[i].keysym);
XUngrabKey(dpy, code, key[i].mod, root);
XGrabKey(dpy, code, key[i].mod, root, True,
GrabModeAsync, GrabModeAsync);
}
}
void
keypress(XEvent *e)
{
XKeyEvent *ev = &e->xkey;
static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
unsigned int i;
KeySym keysym;
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
for(i = 0; i < len; i++)
if((keysym == key[i].keysym) && (key[i].mod == ev->state)) {
if(key[i].func)
key[i].func(&key[i].arg);
return;
}
}
static void
zoom(Arg *arg)
{
Client **l, *c;
if(!sel)
return;
if(sel == getnext(clients) && sel->next) {
if((c = getnext(sel->next)))
sel = c;
}
for(l = &clients; *l && *l != sel; l = &(*l)->next);
*l = sel->next;
sel->next = clients; /* pop */
clients = sel;
arrange(NULL);
focus(sel);
}
static void
max(Arg *arg)
{
if(!sel)
return;
sel->x = sx;
sel->y = sy + bh;
sel->w = sw - 2 * sel->border;
sel->h = sh - 2 * sel->border - bh;
higher(sel);
resize(sel, False);
}
static void
tappend(Arg *arg)
{
if(!sel)
return;
sel->tags[arg->i] = tags[arg->i];
arrange(NULL);
}
static void
ttrunc(Arg *arg)
{
int i;
if(!sel)
return;
for(i = 0; i < TLast; i++)
sel->tags[i] = NULL;
tappend(arg);
}
static void
prevc(Arg *arg)
{
Client *c;
if(!sel)
return;
if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) {
higher(c);
focus(c);
}
}
static void
nextc(Arg *arg)
{
Client *c;
if(!sel)
return;
if(!(c = getnext(sel->next)))
c = getnext(clients);
if(c) {
higher(c);
c->revert = sel;
focus(c);
}
}
static void
ckill(Arg *arg)
{
if(!sel)
return;
if(sel->proto & WM_PROTOCOL_DELWIN)
sendevent(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
else
XKillClient(dpy, sel->win);
}

112
main.c
View file

@ -43,16 +43,16 @@ DC dc = {0};
Client *clients = NULL; Client *clients = NULL;
Client *sel = NULL; Client *sel = NULL;
static Bool other_wm_running; static Bool otherwm;
static const char version[] = static const char version[] =
"dwm-" VERSION ", (C)opyright MMVI Anselm R. Garbe\n"; "dwm-" VERSION ", (C)opyright MMVI Anselm R. Garbe\n";
static int (*x_xerror) (Display *, XErrorEvent *); static int (*xerrorxlib)(Display *, XErrorEvent *);
static void static void
usage() { error("usage: dwm [-v]\n"); } usage() { eprint("usage: dwm [-v]\n"); }
static void static void
scan_wins() scan()
{ {
unsigned int i, num; unsigned int i, num;
Window *wins; Window *wins;
@ -73,6 +73,22 @@ scan_wins()
XFree(wins); XFree(wins);
} }
static void
cleanup()
{
while(sel) {
resize(sel, True);
unmanage(sel);
}
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
}
void
quit(Arg *arg)
{
running = False;
}
static int static int
win_property(Window w, Atom a, Atom t, long l, unsigned char **prop) win_property(Window w, Atom a, Atom t, long l, unsigned char **prop)
{ {
@ -94,7 +110,7 @@ win_property(Window w, Atom a, Atom t, long l, unsigned char **prop)
} }
int int
proto(Window w) getproto(Window w)
{ {
unsigned char *protocols; unsigned char *protocols;
long res; long res;
@ -128,6 +144,17 @@ sendevent(Window w, Atom a, long value)
XFlush(dpy); XFlush(dpy);
} }
/*
* Startup Error handler to check if another window manager
* is already running.
*/
static int
xerrorstart(Display *dsply, XErrorEvent *ee)
{
otherwm = True;
return -1;
}
/* /*
* There's no way to check accesses to destroyed windows, thus * There's no way to check accesses to destroyed windows, thus
* those cases are ignored (especially on UnmapNotify's). * those cases are ignored (especially on UnmapNotify's).
@ -135,52 +162,25 @@ sendevent(Window w, Atom a, long value)
* calls exit(). * calls exit().
*/ */
int int
xerror(Display *dpy, XErrorEvent *error) xerror(Display *dpy, XErrorEvent *ee)
{ {
if(error->error_code == BadWindow if(ee->error_code == BadWindow
|| (error->request_code == X_SetInputFocus || (ee->request_code == X_SetInputFocus
&& error->error_code == BadMatch) && ee->error_code == BadMatch)
|| (error->request_code == X_PolyText8 || (ee->request_code == X_PolyText8
&& error->error_code == BadDrawable) && ee->error_code == BadDrawable)
|| (error->request_code == X_PolyFillRectangle || (ee->request_code == X_PolyFillRectangle
&& error->error_code == BadDrawable) && ee->error_code == BadDrawable)
|| (error->request_code == X_PolySegment || (ee->request_code == X_PolySegment
&& error->error_code == BadDrawable) && ee->error_code == BadDrawable)
|| (error->request_code == X_ConfigureWindow || (ee->request_code == X_ConfigureWindow
&& error->error_code == BadMatch) && ee->error_code == BadMatch)
|| (error->request_code == X_GrabKey || (ee->request_code == X_GrabKey
&& error->error_code == BadAccess)) && ee->error_code == BadAccess))
return 0; return 0;
fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
error->request_code, error->error_code); ee->request_code, ee->error_code);
return x_xerror(dpy, error); /* may call exit() */ return xerrorxlib(dpy, ee); /* may call exit() */
}
/*
* Startup Error handler to check if another window manager
* is already running.
*/
static int
startup_xerror(Display *dpy, XErrorEvent *error)
{
other_wm_running = True;
return -1;
}
static void
cleanup()
{
while(sel) {
resize(sel, True);
unmanage(sel);
}
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
}
void
quit(Arg *arg)
{
running = False;
} }
int int
@ -208,23 +208,23 @@ main(int argc, char *argv[])
dpy = XOpenDisplay(0); dpy = XOpenDisplay(0);
if(!dpy) if(!dpy)
error("dwm: cannot connect X server\n"); eprint("dwm: cannot connect X server\n");
screen = DefaultScreen(dpy); screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen); root = RootWindow(dpy, screen);
/* check if another WM is already running */ /* check if another WM is already running */
other_wm_running = False; otherwm = False;
XSetErrorHandler(startup_xerror); XSetErrorHandler(xerrorstart);
/* this causes an error if some other WM is running */ /* this causes an error if some other WM is running */
XSelectInput(dpy, root, SubstructureRedirectMask); XSelectInput(dpy, root, SubstructureRedirectMask);
XFlush(dpy); XFlush(dpy);
if(other_wm_running) if(otherwm)
error("dwm: another window manager is already running\n"); eprint("dwm: another window manager is already running\n");
XSetErrorHandler(0); XSetErrorHandler(0);
x_xerror = XSetErrorHandler(xerror); xerrorxlib = XSetErrorHandler(xerror);
/* init atoms */ /* init atoms */
wm_atom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); wm_atom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
@ -278,7 +278,7 @@ main(int argc, char *argv[])
XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
strcpy(stext, "dwm-"VERSION); strcpy(stext, "dwm-"VERSION);
scan_wins(); scan();
/* main event loop, reads status text from stdin as well */ /* main event loop, reads status text from stdin as well */
Mainloop: Mainloop:
@ -292,7 +292,7 @@ Mainloop:
if(i == -1 && errno == EINTR) if(i == -1 && errno == EINTR)
continue; continue;
if(i < 0) if(i < 0)
error("select failed\n"); eprint("select failed\n");
else if(i > 0) { else if(i > 0) {
if(FD_ISSET(ConnectionNumber(dpy), &rd)) { if(FD_ISSET(ConnectionNumber(dpy), &rd)) {
while(XPending(dpy)) { while(XPending(dpy)) {

100
screen.c
View file

@ -1,100 +0,0 @@
/*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include "dwm.h"
void (*arrange)(Arg *) = tiling;
void
view(Arg *arg)
{
Client *c;
tsel = arg->i;
arrange(NULL);
for(c = clients; c; c = getnext(c->next))
drawtitle(c);
drawstatus();
}
void
floating(Arg *arg)
{
Client *c;
arrange = floating;
for(c = clients; c; c = c->next) {
if(c->tags[tsel])
resize(c, True);
else
ban(c);
}
if(sel && !sel->tags[tsel]) {
if((sel = getnext(clients))) {
higher(sel);
focus(sel);
}
}
drawstatus();
}
void
tiling(Arg *arg)
{
Client *c;
int n, i, w, h;
w = sw - mw;
arrange = tiling;
for(n = 0, c = clients; c; c = c->next)
if(c->tags[tsel] && !c->floating)
n++;
if(n > 1)
h = (sh - bh) / (n - 1);
else
h = sh - bh;
for(i = 0, c = clients; c; c = c->next) {
if(c->tags[tsel]) {
if(c->floating) {
higher(c);
resize(c, True);
continue;
}
if(n == 1) {
c->x = sx;
c->y = sy + bh;
c->w = sw - 2 * c->border;
c->h = sh - 2 * c->border - bh;
}
else if(i == 0) {
c->x = sx;
c->y = sy + bh;
c->w = mw - 2 * c->border;
c->h = sh - 2 * c->border - bh;
}
else {
c->x = sx + mw;
c->y = sy + (i - 1) * h + bh;
c->w = w - 2 * c->border;
c->h = h - 2 * c->border;
}
resize(c, False);
i++;
}
else
ban(c);
}
if(!sel || (sel && !sel->tags[tsel])) {
if((sel = getnext(clients))) {
higher(sel);
focus(sel);
}
}
drawstatus();
}

171
tag.c Normal file
View file

@ -0,0 +1,171 @@
/*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include "dwm.h"
static Rule rule[] = {
/* class instance tags dofloat */
{ "Firefox-bin", "Gecko", { [Twww] = "www" }, False },
};
void (*arrange)(Arg *) = dotile;
Client *
getnext(Client *c)
{
for(; c && !c->tags[tsel]; c = c->next);
return c;
}
void
settags(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) {
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)))
{
for(j = 0; j < TLast; j++)
c->tags[j] = rule[i].tags[j];
c->dofloat = rule[i].dofloat;
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
view(Arg *arg)
{
tsel = arg->i;
arrange(NULL);
drawall();
}
void
dofloat(Arg *arg)
{
Client *c;
arrange = dofloat;
for(c = clients; c; c = c->next) {
if(c->tags[tsel])
resize(c, True);
else
ban(c);
}
if(sel && !sel->tags[tsel]) {
if((sel = getnext(clients))) {
higher(sel);
focus(sel);
}
}
drawall();
}
void
dotile(Arg *arg)
{
Client *c;
int n, i, w, h;
w = sw - mw;
arrange = dotile;
for(n = 0, c = clients; c; c = c->next)
if(c->tags[tsel] && !c->dofloat)
n++;
if(n > 1)
h = (sh - bh) / (n - 1);
else
h = sh - bh;
for(i = 0, c = clients; c; c = c->next) {
if(c->tags[tsel]) {
if(c->dofloat) {
higher(c);
resize(c, True);
continue;
}
if(n == 1) {
c->x = sx;
c->y = sy + bh;
c->w = sw - 2 * c->border;
c->h = sh - 2 * c->border - bh;
}
else if(i == 0) {
c->x = sx;
c->y = sy + bh;
c->w = mw - 2 * c->border;
c->h = sh - 2 * c->border - bh;
}
else {
c->x = sx + mw;
c->y = sy + (i - 1) * h + bh;
c->w = w - 2 * c->border;
c->h = h - 2 * c->border;
}
resize(c, False);
i++;
}
else
ban(c);
}
if(!sel || (sel && !sel->tags[tsel])) {
if((sel = getnext(clients))) {
higher(sel);
focus(sel);
}
}
drawall();
}
void
appendtag(Arg *arg)
{
if(!sel)
return;
sel->tags[arg->i] = tags[arg->i];
arrange(NULL);
}
void
replacetag(Arg *arg)
{
int i;
if(!sel)
return;
for(i = 0; i < TLast; i++)
sel->tags[i] = NULL;
appendtag(arg);
}

2
util.c
View file

@ -13,7 +13,7 @@
#include "dwm.h" #include "dwm.h"
void void
error(const char *errstr, ...) { eprint(const char *errstr, ...) {
va_list ap; va_list ap;
va_start(ap, errstr); va_start(ap, errstr);
vfprintf(stderr, errstr, ap); vfprintf(stderr, errstr, ap);