wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

commit 5a12c899a534d62e94733d4a4a6fc57372b140e0
parent 21df75141e77ead31a5487709d67f25427a311ca
Author: Kris Maglione <jg@suckless.org>
Date:   Thu, 22 Mar 2007 16:04:47 -0400

Cleanup in main.c. Fixed the bar setup in rc.wmii.

Diffstat:
client.c | 16++++++++--------
draw.c | 2+-
main.c | 382+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
rc/rc.wmii | 2+-
util.c | 16+++++++++++++---
wmii.h | 19+++++++++++--------
6 files changed, 253 insertions(+), 184 deletions(-)

diff --git a/client.c b/client.c @@ -136,7 +136,7 @@ manage_client(Client *c) { XTextProperty tags = { 0 }; Client *trans; - XGetTextProperty(blz.dpy, c->win, &tags, tags_atom); + XGetTextProperty(blz.dpy, c->win, &tags, atom[TagsAtom]); if((trans = client_of_win(c->trans))) strncpy(c->tags, trans->tags, sizeof(c->tags)); @@ -195,7 +195,7 @@ update_client_name(Client *c) { name.nitems = 0; c->name[0] = 0; - XGetTextProperty(blz.dpy, c->win, &name, net_atom[NetWMName]); + XGetTextProperty(blz.dpy, c->win, &name, atom[NetWMName]); if(!name.nitems) XGetWMName(blz.dpy, c->win, &name); if(!name.nitems) @@ -248,8 +248,8 @@ set_client_state(Client * c, int state) { XChangeProperty( /* display */ blz.dpy, /* parent */ c->win, - /* property */ wm_atom[WMState], - /* type */ wm_atom[WMState], + /* property */ atom[WMState], + /* type */ atom[WMState], /* format */ 32, /* mode */ PropModeReplace, /* data */ (uchar *) data, @@ -355,7 +355,7 @@ send_client_message(Window w, Atom a, long value) { void kill_client(Client * c) { if(c->proto & WM_PROTOCOL_DELWIN) - send_client_message(c->win, wm_atom[WMProtocols], wm_atom[WMDelete]); + send_client_message(c->win, atom[WMProtocols], atom[WMDelete]); else XKillClient(blz.dpy, c->win); } @@ -409,9 +409,9 @@ prop_client(Client *c, Atom a) { XWMHints *wmh; long msize; - if(a == wm_atom[WMProtocols]) + if(a == atom[WMProtocols]) c->proto = win_proto(c->win); - else if(a== net_atom[NetWMName]) { + else if(a== atom[NetWMName]) { wmname: update_client_name(c); if(c->frame) @@ -933,7 +933,7 @@ apply_tags(Client *c, const char *tags) { toks[n] = nil; update_client_views(c, toks); - XChangeProperty(blz.dpy, c->win, tags_atom, XA_STRING, 8, + XChangeProperty(blz.dpy, c->win, atom[TagsAtom], XA_STRING, 8, PropModeReplace, (uchar *)c->tags, strlen(c->tags)); } diff --git a/draw.c b/draw.c @@ -54,7 +54,7 @@ loadfont(Blitz *blitz, BlitzFont *font) { font->xfont = XLoadQueryFont(blitz->dpy, fontname); if (!font->xfont) { if(!strncmp(fontname, BLITZ_FONT, sizeof(BLITZ_FONT))) - fatal("wmiiwm: error, cannot load '%s' font\n", + fatal("cannot load font: %s", BLITZ_FONT); free(font->fontstr); font->fontstr = estrdup(BLITZ_FONT); diff --git a/main.c b/main.c @@ -19,10 +19,16 @@ #include <unistd.h> #include "wmii.h" -static Bool check_other_wm; +#define nelem(ary) (sizeof(ary) / sizeof(*ary)) + +static const char + version[] = "wmiiwm - " VERSION ", ©2007 Kris Maglione\n"; + static int (*x_error_handler) (Display *, XErrorEvent *); -static char version[] = "wmiiwm - " VERSION ", © 2007 Kris Maglione\n"; +static char *address, *ns_path; +static Bool check_other_wm; static struct sigaction sa; +static struct passwd *passwd; static int sleeperfd; static void @@ -59,55 +65,136 @@ scan_wins() { XFree(wins); } -static int -win_property(Window w, Atom a, Atom t, long l, uchar **prop) { +int +win_proto(Window w) { + Atom *protocols; Atom real; - int format; - ulong res, extra; - int status; + ulong nitems, extra; + int i, format, status, protos; + + status = XGetWindowProperty( + /* display */ blz.dpy, + /* window */ w, + /* property */ atom[WMProtocols], + /* offset */ 0L, + /* length */ 20L, + /* delete */ False, + /* req_type */ XA_ATOM, + /* type_ret */ &real, + /* format_ret */&format, + /* nitems_ret */&nitems, + /* extra_bytes */&extra, + /* prop_return */(uchar**)&protocols + ); + + if(status != Success || protocols == 0) { + return 0; + } - status = XGetWindowProperty(blz.dpy, w, a, 0L, l, False, t, &real, &format, - &res, &extra, prop); - if(status != Success || *prop == 0) { + if(nitems == 0) { + free(protocols); return 0; } - if(res == 0) { - free((void *) *prop); + + protos = 0; + for(i = 0; i < nitems; i++) { + if(protocols[i] == atom[WMDelete]) + protos |= WM_PROTOCOL_DELWIN; } - return res; + + free(protocols); + return protos; } -int -win_proto(Window w) { - Atom *protocols; - long res; - int protos = 0; - int i; +static void +init_ns() { + struct stat st; + char *p, *q, *display; + int ret; - res = win_property(w, wm_atom[WMProtocols], XA_ATOM, 20L, - ((uchar **) &protocols)); - if(res <= 0) { - return protos; + if(address && strncmp(address, "unix!", 5) == 0) { + ns_path = estrdup(&address[5]); + + p = strrchr(ns_path, '/'); + if(p != nil) + p = '\0'; + }else if((p = getenv("WMII_NS_PATH")) || (p = getenv("NAMESPACE"))) + ns_path = p; + else { + display = getenv("DISPLAY"); + if(display == nil) + fatal("DISPLAY is unset"); + + display = estrdup(display); + p = &display[strlen(display) - 2]; + if(strcmp(p, ".0") == 0) + *p = '\0'; + + ns_path = emalloc(strlen(display) + strlen(user) + strlen("/tmp/ns..") + 1); + sprintf(ns_path, "/tmp/ns.%s.%s", user, display); } - for(i = 0; i < res; i++) { - if(protocols[i] == wm_atom[WMDelete]) - protos |= WM_PROTOCOL_DELWIN; + + if(ns_path[0] != '/' || strlen(ns_path) == 0) + fatal("Bad ns_path"); + + q = ns_path + strlen(ns_path); + for(p = &ns_path[1]; p < q; p++) { + if(*p == '/') { + *p = '\0'; + ret = mkdir(ns_path, 0700); + if(ret == -1 && errno != EEXIST) + fatal("Can't create ns_path '%s':", ns_path); + *p = '/'; + } } - free((char *) protocols); - return protos; + + if(stat(ns_path, &st)) + fatal("Can't stat ns_path '%s':", ns_path); + if(getuid() != st.st_uid) + fatal("ns_path '%s' exists but is not owned by you", + ns_path); + if(st.st_mode & 077) + fatal("ns_path '%s' exists, but has group or world permissions", + ns_path); +} + +static void +init_environment() { + if(address == nil) + address = getenv("WMII_ADDRESS"); + + init_ns(); + + if(address == nil) { + address = emalloc(strlen(ns_path) + strlen("unix!/wmii") + 1); + sprintf(address, "unix!%s/wmii", ns_path); + } + + setenv("WMII_NS_DIR", ns_path, True); + setenv("WMII_ADDRESS", address, True); } +static void +intern_atom(int ident, char *name) { + atom[ident] = XInternAtom(blz.dpy, name, False); +} static void init_atoms() { - wm_atom[WMState] = XInternAtom(blz.dpy, "WM_STATE", False); - wm_atom[WMProtocols] = XInternAtom(blz.dpy, "WM_PROTOCOLS", False); - wm_atom[WMDelete] = XInternAtom(blz.dpy, "WM_DELETE_WINDOW", False); - net_atom[NetSupported] = XInternAtom(blz.dpy, "_NET_SUPPORTED", False); - net_atom[NetWMName] = XInternAtom(blz.dpy, "_NET_WM_NAME", False); - tags_atom = XInternAtom(blz.dpy, "_WIN_TAGS", False); - XChangeProperty(blz.dpy, blz.root, net_atom[NetSupported], XA_ATOM, 32, - PropModeReplace, (uchar *) net_atom, NetLast); + intern_atom(WMState, "WM_STATE"); + intern_atom(WMProtocols, "WM_PROTOCOLS"); + intern_atom(WMDelete, "WM_DELETE_WINDOW"); + intern_atom(NetSupported, "_NET_SUPPORTED"); + intern_atom(NetWMName, "_NET_WM_NAME"); + intern_atom(TagsAtom, "_WIN_TAGS"); + + XChangeProperty(blz.dpy, blz.root, atom[NetSupported], XA_ATOM, 32, + PropModeReplace, (uchar *)&atom[NetSupported], 2); +} + +static void +create_cursor(int ident, uint shape) { + cursor[ident] = XCreateFontCursor(blz.dpy, shape); } static void @@ -115,17 +202,24 @@ init_cursors() { Pixmap pix; XColor black, dummy; - XAllocNamedColor(blz.dpy, DefaultColormap(blz.dpy, blz.screen), "black", &black, &dummy); - pix = XCreateBitmapFromData(blz.dpy, blz.root, (char[]){0}, 1, 1); - - cursor[CurNormal] = XCreateFontCursor(blz.dpy, XC_left_ptr); - cursor[CurNECorner] = XCreateFontCursor(blz.dpy, XC_top_right_corner); - cursor[CurNWCorner] = XCreateFontCursor(blz.dpy, XC_top_left_corner); - cursor[CurSECorner] = XCreateFontCursor(blz.dpy, XC_bottom_right_corner); - cursor[CurSWCorner] = XCreateFontCursor(blz.dpy, XC_bottom_left_corner); - cursor[CurMove] = XCreateFontCursor(blz.dpy, XC_fleur); - cursor[CurInput] = XCreateFontCursor(blz.dpy, XC_xterm); - cursor[CurInvisible] = XCreatePixmapCursor(blz.dpy, pix, pix, &black, &black, 0, 0); + create_cursor(CurNormal, XC_left_ptr); + create_cursor(CurNECorner, XC_top_right_corner); + create_cursor(CurNWCorner, XC_top_left_corner); + create_cursor(CurSECorner, XC_bottom_right_corner); + create_cursor(CurSWCorner, XC_bottom_left_corner); + create_cursor(CurMove, XC_fleur); + create_cursor(CurInput, XC_xterm); + + XAllocNamedColor(blz.dpy, DefaultColormap(blz.dpy, blz.screen), + "black", &black, + &dummy); + pix = XCreateBitmapFromData(blz.dpy, blz.root, + (char[]){0}, 1, 1); + + cursor[CurInvisible] = XCreatePixmapCursor(blz.dpy, + pix, pix, + &black, &black, + 0, 0); XFreePixmap(blz.dpy, pix); } @@ -142,13 +236,23 @@ init_screen(WMScreen *screen) { gcv.foreground = def.normcolor.bg; gcv.plane_mask = AllPlanes; gcv.graphics_exposures = False; - xorgc = XCreateGC(blz.dpy, blz.root, GCForeground | GCGraphicsExposures | - GCFunction | GCSubwindowMode | GCPlaneMask, &gcv); + xorgc = XCreateGC(blz.dpy, blz.root, + GCForeground + | GCGraphicsExposures + | GCFunction + | GCSubwindowMode + | GCPlaneMask, + &gcv); + screen->rect.x = screen->rect.y = 0; screen->rect.width = DisplayWidth(blz.dpy, blz.screen); screen->rect.height = DisplayHeight(blz.dpy, blz.screen); def.snap = screen->rect.height / 63; - sel_screen = XQueryPointer(blz.dpy, blz.root, &w, &w, &ret, &ret, &ret, &ret, &mask); + + sel_screen = XQueryPointer(blz.dpy, blz.root, + &w, &w, + &ret, &ret, &ret, &ret, + &mask); } /* @@ -160,21 +264,23 @@ init_screen(WMScreen *screen) { int wmii_error_handler(Display *dpy, XErrorEvent *error) { if(check_other_wm) - fatal("wmiiwm: another window manager is already running\n"); + fatal("another window manager is already running"); + 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)) + ||(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, "wmiiwm: fatal error: Xrequest code=%d, Xerror code=%d\n", error->request_code, error->error_code); return x_error_handler(blz.dpy, error); /* calls exit() */ @@ -193,6 +299,7 @@ static void cleanup_handler(int signal) { sa.sa_handler = SIG_DFL; sigaction(signal, &sa, nil); + switch(signal) { case SIGINT: srv.running = False; @@ -211,33 +318,41 @@ init_traps() { int fd[2]; if(pipe(fd) != 0) - fatal("Can't pipe(): %s\n", strerror(errno)); + fatal("Can't pipe():"); switch(fork()) { case -1: - fatal("Can't fork(): %s\n", strerror(errno)); - default: - close(fd[0]); - sleeperfd = fd[1]; - sa.sa_flags = 0; - sa.sa_handler = cleanup_handler; - sigaction(SIGINT, &sa, nil); - sigaction(SIGTERM, &sa, nil); - sigaction(SIGQUIT, &sa, nil); - sigaction(SIGHUP, &sa, nil); - break; + fatal("Can't fork():"); + break; /* not reached */ case 0: close(fd[1]); close(ConnectionNumber(blz.dpy)); setsid(); + blz.dpy = XOpenDisplay(0); if(!blz.dpy) - fatal("wmiiwm: cannot open display\n"); + fatal("Can't open display"); + + /* Wait for parent to exit */ read(fd[0], buf, 1); + + /* Reset input focus */ XSetInputFocus(blz.dpy, PointerRoot, RevertToPointerRoot, CurrentTime); XCloseDisplay(blz.dpy); exit(0); + default: + break; } + + close(fd[0]); + sleeperfd = fd[1]; + + sa.sa_flags = 0; + sa.sa_handler = cleanup_handler; + sigaction(SIGINT, &sa, nil); + sigaction(SIGTERM, &sa, nil); + sigaction(SIGQUIT, &sa, nil); + sigaction(SIGHUP, &sa, nil); } void @@ -248,9 +363,7 @@ check_9pcon(IXPConn *c) { int main(int argc, char *argv[]) { - char *wmiirc, *errstr, *tmp, *display; - char address[1024], ns_path[1024]; - struct passwd *passwd; + char *wmiirc, *errstr, *p; WMScreen *s; int sock, i; pid_t pid; @@ -259,12 +372,6 @@ main(int argc, char *argv[]) { passwd = getpwuid(getuid()); user = estrdup(passwd->pw_name); wmiirc = "wmiistartrc"; - address[0] = '\0'; - - display = strdup(getenv("DISPLAY")); - if((tmp = strstr(display, ".0")) == display + strlen(display) - 2) - *tmp = '\0'; - /* command line args */ for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) { @@ -277,14 +384,18 @@ main(int argc, char *argv[]) { verbose = True; break; case 'a': - if(i + 1 < argc) - strncpy(address, argv[++i], sizeof(address)); + if(argv[i][2] != '\0') + address = &argv[i][2]; + else if(++i < argc) + address = argv[i]; else usage(); break; case 'r': - if(i + 1 < argc) - wmiirc = argv[++i]; + if(argv[i][2] != '\0') + wmiirc = &argv[i][2]; + else if(++i < argc) + wmiirc = argv[i]; else usage(); break; @@ -294,35 +405,12 @@ main(int argc, char *argv[]) { } } - - if((strlen(address) == 0) - && (tmp = getenv("WMII_ADDRESS")) && strlen(tmp) > 0) - strncpy(address, tmp, sizeof(address)); - - if(strncmp(address, "unix!", 5) == 0) { - tmp = &address[5]; - i = strrchr(tmp, '/') - tmp; - if(i < 0) - fatal("wmiiwm: Bad address\n"); - strncpy(ns_path, tmp, min(sizeof(ns_path), i)); - } - else if((tmp = getenv("WMII_NS_DIR")) && strlen(tmp) > 0) - strncpy(ns_path, tmp, sizeof(ns_path)); - else - snprintf(ns_path, sizeof(ns_path), "/tmp/ns.%s.%s", user, display); - - if(strlen(address) == 0) - snprintf(address, sizeof(address), "unix!%s/wmii", ns_path); - - setenv("WMII_NS_DIR", ns_path, True); - setenv("WMII_ADDRESS", address, True); - setlocale(LC_CTYPE, ""); starting = True; blz.dpy = XOpenDisplay(0); if(!blz.dpy) - fatal("wmiiwm: cannot open dpy\n"); + fatal("Can't open display"); blz.screen = DefaultScreen(blz.dpy); blz.root = RootWindow(blz.dpy, blz.screen); @@ -332,76 +420,43 @@ main(int argc, char *argv[]) { XSync(blz.dpy, False); check_other_wm = False; + init_environment(); init_traps(); - /* Make sure that the namespace directory exists */ - switch(pid = fork()) { - case -1: - fatal("wmiiwm: Can't fork: %s\n", strerror(errno)); - break; /* Not reached */ - case 0: - execlp("mkdir", "mkdir", "-m", "0700", "-p", ns_path, nil); - fatal("wmiiwm: Can't exec mkdir: %s\n", strerror(errno)); - break; /* Not reached */ - default: - if(waitpid(pid, &i, WUNTRACED) == -1) - fprintf(stderr, "wmiiwm: warning: wait for mkdir returned -1: %s\n", - strerror(errno)); - else if(WEXITSTATUS(i) != 0) - fatal("wmiiwm: Can't create namespace dir \"%s\" (mkdir returned %d)\n", - ns_path, i); - break; - } - - /* Check namespace permissions */ - if(!strncmp(address, "unix!", 5)) { - struct stat st; - - if(stat(ns_path, &st)) - fatal("wmiiwm: can't stat ns_path directory \"%s\": %s\n", - ns_path, strerror(errno)); - if(getuid() != st.st_uid) - fatal("wmiiwm: ns_path directory \"%s\" exists, " - "but is not owned by you", - ns_path); - if(st.st_mode & 077) - fatal("wmiiwm: ns_path directory \"%s\" exists, " - "but has group or world permissions", - ns_path); - } - errstr = nil; sock = ixp_create_sock(address, &errstr); if(sock < 0) - fatal("wmiiwm: fatal: %s (%s)\n", errstr, address); + fatal("Can't create socket '%s': %s", address, errstr); /* start wmiirc */ if(wmiirc) { + char *shell; + /* Double fork hack */ switch(pid = fork()) { case -1: - perror("wmiiwm: cannot fork wmiirc"); + fatal("Can't fork wmiirc"); break; /* Not reached */ case 0: switch(fork()) { case -1: - perror("wmiiwm: cannot fork wmiirc"); + fatal("Can't fork wmiirc"); break; /* Not reached */ case 0: if(setsid() == -1) - fatal("wmiiwm: can't setsid: %s\n", strerror(errno)); + fatal("Can't setsid:"); close(sock); close(ConnectionNumber(blz.dpy)); + shell = passwd->pw_shell; + if(shell[0] != '/') + fatal("Shell is not an absolute path: %s", shell); /* Run through the user's shell as a login shell */ - tmp = malloc(sizeof(char*) * (strlen(passwd->pw_shell) + 2)); - if(passwd->pw_shell[0] == '/') - sprintf(tmp, "-%s", strrchr(passwd->pw_shell, '/') + 1); /* Can't overflow */ - else - fatal("wmiiwm: shell is not an absolute path: %s\n", passwd->pw_shell); - - execl(passwd->pw_shell, tmp, "-c", wmiirc, nil); - fatal("wmiiwm: can't exec \"%s\": %s\n", wmiirc, strerror(errno)); + p = malloc(sizeof(char*) * (strlen(shell) + 2)); + sprintf(p, "-%s", strrchr(shell, '/') + 1); + + execl(shell, p, "-c", wmiirc, nil); + fatal("Can't exec '%s':", wmiirc); break; /* Not reached */ default: exit(0); @@ -514,15 +569,16 @@ main(int argc, char *argv[]) { check_x_event(nil); errstr = ixp_server_loop(&srv); if(errstr) - fprintf(stderr, "wmiiwm: fatal: %s\n", errstr); cleanup(); XCloseDisplay(blz.dpy); ixp_server_close(&srv); close(sleeperfd); + if(execstr) execl("/bin/sh", "sh", "-c", execstr, nil); + if(errstr) - return 1; + fatal("%s", errstr); return 0; } diff --git a/rc/rc.wmii b/rc/rc.wmii @@ -211,7 +211,7 @@ proglist $PATH >$progs_file & # Tag Bar Setup ifs='# -'{ for(bar in `{comm -1 <{wmiir ls /lbar} <{read_tags}}) +'{ for(bar in `{comm -23 <{wmiir ls /lbar} <{read_tags}}) wmiir remove /lbar/$bar seltag=`{wmiir read /tag/sel/ctl} for(tag in `{read_tags}) { diff --git a/util.c b/util.c @@ -1,5 +1,6 @@ /* Written by Kris Maglione <fbsdaemon at gmail dot com> */ /* Public domain */ +#include <errno.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -9,11 +10,20 @@ void fatal(const char *fmt, ...) { va_list ap; + int err; + + err = errno; + fprintf(stderr, "wmiiwm: fatal: "); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); + if(fmt[strlen(fmt)-1] == ':') + fprintf(stderr, " %s\n", strerror(err)); + else + fprintf(stderr, "\n"); + exit(1); } @@ -21,7 +31,7 @@ void * emalloc(uint size) { void *ret = malloc(size); if(!ret) - fatal("fatal: could not malloc() %d bytes\n", size); + fatal("could not malloc() %d bytes", size); return ret; } @@ -36,7 +46,7 @@ void * erealloc(void *ptr, uint size) { void *ret = realloc(ptr, size); if(!ret) - fatal("fatal: could not realloc() %d bytes\n", size); + fatal("fatal: could not realloc() %d bytes", size); return ret; } @@ -44,7 +54,7 @@ char * estrdup(const char *str) { void *ret = strdup(str); if(!ret) - fatal("fatal: could not strdup() %u bytes\n", strlen(str)); + fatal("fatal: could not strdup() %u bytes", strlen(str)); return ret; } diff --git a/wmii.h b/wmii.h @@ -88,11 +88,16 @@ struct BlitzBrush { XRectangle rect; /* relative rect */ }; -/* WM atoms */ -enum { WMState, WMProtocols, WMDelete, WMLast }; - -/* NET atoms */ -enum { NetSupported, NetWMName, NetLast }; +enum { +/* WM atom */ + WMState, WMProtocols, WMDelete, +/* NET atom */ + NetSupported, NetWMName, +/* Other */ + TagsAtom, +/* Last atom */ + AtomLast +}; /* Column modes */ enum { Coldefault, Colstack, Colmax }; @@ -256,9 +261,7 @@ uint num_screens; Blitz blz; GC xorgc; char *user; -Atom wm_atom[WMLast]; -Atom net_atom[NetLast]; -Atom tags_atom; +Atom atom[AtomLast]; Cursor cursor[CurLast]; uint valid_mask; uint num_lock_mask;