Skip to content
Snippets Groups Projects
Commit dba23062 authored by Anselm R. Garbe's avatar Anselm R. Garbe
Browse files

rearranged several stuff

parent c0705eeb
Branches
Tags
No related merge requests found
......@@ -3,7 +3,7 @@
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}
MAN1 = dwm.1
BIN = dwm
......
......@@ -11,18 +11,6 @@
#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
ban(Client *c)
{
......@@ -31,7 +19,7 @@ ban(Client *c)
}
static void
resize_title(Client *c)
resizetitle(Client *c)
{
int i;
......@@ -72,7 +60,7 @@ settitle(Client *c)
}
}
XFree(name.value);
resize_title(c);
resizetitle(c);
}
void
......@@ -143,42 +131,6 @@ focus(Client *c)
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
manage(Window w, XWindowAttributes *wa)
{
......@@ -196,7 +148,7 @@ manage(Window w, XWindowAttributes *wa)
c->h = wa->height;
c->th = bh;
c->border = 1;
c->proto = proto(c->win);
c->proto = getproto(c->win);
setsize(c);
XSelectInput(dpy, c->win,
StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
......@@ -211,7 +163,7 @@ manage(Window w, XWindowAttributes *wa)
CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
settitle(c);
init_tags(c);
settags(c);
for(l = &clients; *l; l = &(*l)->next);
c->next = *l; /* *l == nil */
......@@ -224,8 +176,8 @@ manage(Window w, XWindowAttributes *wa)
XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask,
GrabModeAsync, GrabModeSync, None, None);
if(!c->floating)
c->floating = trans
if(!c->dofloat)
c->dofloat = trans
|| ((c->maxw == c->minw) && (c->maxh == c->minh));
arrange(NULL);
......@@ -321,7 +273,7 @@ resize(Client *c, Bool inc)
c->w = c->maxw;
if(c->maxh && c->h > c->maxh)
c->h = c->maxh;
resize_title(c);
resizetitle(c);
XSetWindowBorderWidth(dpy, c->win, 1);
XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
e.type = ConfigureNotify;
......@@ -339,7 +291,7 @@ resize(Client *c, Bool inc)
}
static int
dummy_xerror(Display *dsply, XErrorEvent *err)
xerrordummy(Display *dsply, XErrorEvent *ee)
{
return 0;
}
......@@ -350,7 +302,7 @@ unmanage(Client *c)
Client **l;
XGrabServer(dpy);
XSetErrorHandler(dummy_xerror);
XSetErrorHandler(xerrordummy);
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
XDestroyWindow(dpy, c->title);
......@@ -374,7 +326,7 @@ unmanage(Client *c)
}
Client *
gettitle(Window w)
getctitle(Window w)
{
Client *c;
for(c = clients; c; c = c->next)
......@@ -392,3 +344,80 @@ getclient(Window w)
return c;
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);
}
......@@ -10,34 +10,43 @@
#include "dwm.h"
void
drawall()
{
Client *c;
for(c = clients; c; c = getnext(c->next))
drawtitle(c);
drawstatus();
}
void
drawstatus()
{
int i;
Bool istile = arrange == dotile;
dc.x = dc.y = 0;
dc.w = bw;
drawtext(NULL, False, False);
drawtext(NULL, !istile, False);
if(arrange == floating) {
dc.w = textw("~");
drawtext("~", False, False);
}
else
dc.w = 0;
dc.w = 0;
for(i = 0; i < TLast; i++) {
dc.x += dc.w;
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) {
dc.x += dc.w;
dc.w = textw(sel->name);
drawtext(sel->name, True, True);
drawtext(sel->name, istile, True);
}
dc.w = textw(stext);
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);
XFlush(dpy);
......@@ -47,6 +56,8 @@ void
drawtitle(Client *c)
{
int i;
Bool istile = arrange == dotile;
if(c == sel) {
drawstatus();
XUnmapWindow(dpy, c->title);
......@@ -64,12 +75,12 @@ drawtitle(Client *c)
if(c->tags[i]) {
dc.x += dc.w;
dc.w = textw(c->tags[i]);
drawtext(c->tags[i], False, True);
drawtext(c->tags[i], !istile, True);
}
}
dc.x += dc.w;
dc.w = textw(c->name);
drawtext(c->name, False, True);
drawtext(c->name, !istile, True);
XCopyArea(dpy, dc.drawable, c->title, dc.gc,
0, 0, c->tw, c->th, 0, 0);
XFlush(dpy);
......@@ -215,7 +226,7 @@ setfont(const char *fontstr)
if (!dc.font.xfont)
dc.font.xfont = XLoadQueryFont(dpy, "fixed");
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.descent = dc.font.xfont->descent;
}
......
......@@ -66,7 +66,7 @@ struct Client {
int grav;
unsigned int border;
long flags;
Bool floating;
Bool dofloat;
Window win;
Window title;
Client *next;
......@@ -77,7 +77,7 @@ struct Rule {
const char *class;
const char *instance;
char *tags[TLast];
Bool floating;
Bool dofloat;
};
struct Key {
......@@ -103,6 +103,7 @@ extern DC dc;
extern Client *clients, *sel;
/* client.c */
extern void ban(Client *c);
extern void manage(Window w, XWindowAttributes *wa);
extern void unmanage(Client *c);
extern Client *getclient(Window w);
......@@ -110,14 +111,18 @@ extern void focus(Client *c);
extern void settitle(Client *c);
extern void resize(Client *c, Bool inc);
extern void setsize(Client *c);
extern Client *gettitle(Window w);
extern Client *getctitle(Window w);
extern void higher(Client *c);
extern void lower(Client *c);
extern void gravitate(Client *c, Bool invert);
extern void ban(Client *c);
extern Client *getnext(Client *c);
extern void zoom(Arg *arg);
extern void maximize(Arg *arg);
extern void focusprev(Arg *arg);
extern void focusnext(Arg *arg);
extern void killclient(Arg *arg);
/* draw.c */
extern void drawall();
extern void drawstatus();
extern void drawtitle(Client *c);
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 texth(void);
/* key.c */
/* event.c */
extern void grabkeys();
extern void keypress(XEvent *e);
/* 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 int xerror(Display *dsply, XErrorEvent *ee);
extern void sendevent(Window w, Atom a, long value);
extern int getproto(Window w);
/* screen.c */
extern void floating(Arg *arg);
extern void tiling(Arg *arg);
/* tag.c */
extern Client *getnext(Client *c);
extern void settags(Client *c);
extern void dofloat(Arg *arg);
extern void dotile(Arg *arg);
extern void view(Arg *arg);
extern void appendtag(Arg *arg);
extern void replacetag(Arg *arg);
/* util.c */
extern void error(const char *errstr, ...);
extern void eprint(const char *errstr, ...);
extern void *emallocz(unsigned int size);
extern void spawn(Arg *arg);
......@@ -16,6 +16,44 @@
#define ButtonMask (ButtonPressMask | ButtonReleaseMask)
#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 */
static void buttonpress(XEvent *e);
static void configurerequest(XEvent *e);
......@@ -23,6 +61,7 @@ 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 maprequest(XEvent *e);
static void propertynotify(XEvent *e);
static void unmapnotify(XEvent *e);
......@@ -40,8 +79,40 @@ void (*handler[LASTEvent]) (XEvent *) = {
[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
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
mresize(Client *c)
resizemouse(Client *c)
{
XEvent ev;
int ocx, ocy;
......@@ -75,7 +146,7 @@ mresize(Client *c)
}
static void
mmove(Client *c)
movemouse(Client *c)
{
XEvent ev;
int x1, y1, ocx, ocy, di;
......@@ -117,7 +188,7 @@ buttonpress(XEvent *e)
Client *c;
if(barwin == ev->window) {
x = (arrange == floating) ? textw("~") : 0;
x = (arrange == dofloat) ? textw("~") : 0;
for(a.i = 0; a.i < TLast; a.i++) {
x += textw(tags[a.i]);
if(ev->x < x) {
......@@ -127,20 +198,20 @@ buttonpress(XEvent *e)
}
}
else if((c = getclient(ev->window))) {
if(arrange == tiling && !c->floating)
if(arrange == dotile && !c->dofloat)
return;
higher(c);
switch(ev->button) {
default:
break;
case Button1:
mmove(c);
movemouse(c);
break;
case Button2:
lower(c);
break;
case Button3:
mresize(c);
resizemouse(c);
break;
}
}
......@@ -226,7 +297,7 @@ expose(XEvent *e)
if(ev->count == 0) {
if(barwin == ev->window)
drawstatus();
else if((c = gettitle(ev->window)))
else if((c = getctitle(ev->window)))
drawtitle(c);
}
}
......@@ -262,14 +333,14 @@ propertynotify(XEvent *e)
if((c = getclient(ev->window))) {
if(ev->atom == wm_atom[WMProtocols]) {
c->proto = proto(c->win);
c->proto = getproto(c->win);
return;
}
switch (ev->atom) {
default: break;
case XA_WM_TRANSIENT_FOR:
XGetTransientForHint(dpy, c->win, &trans);
if(!c->floating && (c->floating = (trans != 0)))
if(!c->dofloat && (c->dofloat = (trans != 0)))
arrange(NULL);
break;
case XA_WM_NORMAL_HINTS:
......
/*
* (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);
}
......@@ -43,16 +43,16 @@ DC dc = {0};
Client *clients = NULL;
Client *sel = NULL;
static Bool other_wm_running;
static Bool otherwm;
static const char version[] =
"dwm-" VERSION ", (C)opyright MMVI Anselm R. Garbe\n";
static int (*x_xerror) (Display *, XErrorEvent *);
static int (*xerrorxlib)(Display *, XErrorEvent *);
static void
usage() { error("usage: dwm [-v]\n"); }
usage() { eprint("usage: dwm [-v]\n"); }
static void
scan_wins()
scan()
{
unsigned int i, num;
Window *wins;
......@@ -73,6 +73,22 @@ scan_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
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
proto(Window w)
getproto(Window w)
{
unsigned char *protocols;
long res;
......@@ -128,59 +144,43 @@ sendevent(Window w, Atom a, long value)
XFlush(dpy);
}
/*
* There's no way to check accesses to destroyed windows, thus
* those cases are ignored (especially on UnmapNotify's).
* Other types of errors call Xlib's default error handler, which
* calls exit().
*/
int
xerror(Display *dpy, XErrorEvent *error)
{
if(error->error_code == BadWindow
|| (error->request_code == X_SetInputFocus
&& error->error_code == BadMatch)
|| (error->request_code == X_PolyText8
&& error->error_code == BadDrawable)
|| (error->request_code == X_PolyFillRectangle
&& error->error_code == BadDrawable)
|| (error->request_code == X_PolySegment
&& error->error_code == BadDrawable)
|| (error->request_code == X_ConfigureWindow
&& error->error_code == BadMatch)
|| (error->request_code == X_GrabKey
&& error->error_code == BadAccess))
return 0;
fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
error->request_code, error->error_code);
return x_xerror(dpy, error); /* may call exit() */
}
/*
* Startup Error handler to check if another window manager
* is already running.
*/
static int
startup_xerror(Display *dpy, XErrorEvent *error)
xerrorstart(Display *dsply, XErrorEvent *ee)
{
other_wm_running = True;
otherwm = True;
return -1;
}
static void
cleanup()
{
while(sel) {
resize(sel, True);
unmanage(sel);
}
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
}
void
quit(Arg *arg)
/*
* There's no way to check accesses to destroyed windows, thus
* those cases are ignored (especially on UnmapNotify's).
* Other types of errors call Xlib's default error handler, which
* calls exit().
*/
int
xerror(Display *dpy, XErrorEvent *ee)
{
running = False;
if(ee->error_code == BadWindow
|| (ee->request_code == X_SetInputFocus
&& ee->error_code == BadMatch)
|| (ee->request_code == X_PolyText8
&& ee->error_code == BadDrawable)
|| (ee->request_code == X_PolyFillRectangle
&& ee->error_code == BadDrawable)
|| (ee->request_code == X_PolySegment
&& ee->error_code == BadDrawable)
|| (ee->request_code == X_ConfigureWindow
&& ee->error_code == BadMatch)
|| (ee->request_code == X_GrabKey
&& ee->error_code == BadAccess))
return 0;
fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
ee->request_code, ee->error_code);
return xerrorxlib(dpy, ee); /* may call exit() */
}
int
......@@ -208,23 +208,23 @@ main(int argc, char *argv[])
dpy = XOpenDisplay(0);
if(!dpy)
error("dwm: cannot connect X server\n");
eprint("dwm: cannot connect X server\n");
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
/* check if another WM is already running */
other_wm_running = False;
XSetErrorHandler(startup_xerror);
otherwm = False;
XSetErrorHandler(xerrorstart);
/* this causes an error if some other WM is running */
XSelectInput(dpy, root, SubstructureRedirectMask);
XFlush(dpy);
if(other_wm_running)
error("dwm: another window manager is already running\n");
if(otherwm)
eprint("dwm: another window manager is already running\n");
XSetErrorHandler(0);
x_xerror = XSetErrorHandler(xerror);
xerrorxlib = XSetErrorHandler(xerror);
/* init atoms */
wm_atom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
......@@ -278,7 +278,7 @@ main(int argc, char *argv[])
XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
strcpy(stext, "dwm-"VERSION);
scan_wins();
scan();
/* main event loop, reads status text from stdin as well */
Mainloop:
......@@ -292,7 +292,7 @@ Mainloop:
if(i == -1 && errno == EINTR)
continue;
if(i < 0)
error("select failed\n");
eprint("select failed\n");
else if(i > 0) {
if(FD_ISSET(ConnectionNumber(dpy), &rd)) {
while(XPending(dpy)) {
......
......@@ -3,29 +3,78 @@
* 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"
void (*arrange)(Arg *) = tiling;
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
view(Arg *arg)
settags(Client *c)
{
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);
for(c = clients; c; c = getnext(c->next))
drawtitle(c);
drawstatus();
drawall();
}
void
floating(Arg *arg)
dofloat(Arg *arg)
{
Client *c;
arrange = floating;
arrange = dofloat;
for(c = clients; c; c = c->next) {
if(c->tags[tsel])
resize(c, True);
......@@ -38,19 +87,19 @@ floating(Arg *arg)
focus(sel);
}
}
drawstatus();
drawall();
}
void
tiling(Arg *arg)
dotile(Arg *arg)
{
Client *c;
int n, i, w, h;
w = sw - mw;
arrange = tiling;
arrange = dotile;
for(n = 0, c = clients; c; c = c->next)
if(c->tags[tsel] && !c->floating)
if(c->tags[tsel] && !c->dofloat)
n++;
if(n > 1)
......@@ -60,7 +109,7 @@ tiling(Arg *arg)
for(i = 0, c = clients; c; c = c->next) {
if(c->tags[tsel]) {
if(c->floating) {
if(c->dofloat) {
higher(c);
resize(c, True);
continue;
......@@ -95,6 +144,28 @@ tiling(Arg *arg)
focus(sel);
}
}
drawstatus();
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);
}
......@@ -13,7 +13,7 @@
#include "dwm.h"
void
error(const char *errstr, ...) {
eprint(const char *errstr, ...) {
va_list ap;
va_start(ap, errstr);
vfprintf(stderr, errstr, ap);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment