Introduction
Introduction Statistics Contact Development Disclaimer Help
Style inquistion was here. - tabbed - tab interface for application supporting …
git clone git://git.suckless.org/tabbed
Log
Files
Refs
README
LICENSE
---
commit 3f0067b1c775a7f0ade805e10546272f8ce01dd3
parent bcf3d90ce7d93bf2a34c2bec3b2fdd2a7c5e0af0
Author: Christoph Lohmann <[email protected]>
Date: Thu, 8 Nov 2012 21:40:58 +0100
Style inquistion was here.
Diffstat:
M tabbed.c | 193 +++++++++++++++++++++--------…
1 file changed, 129 insertions(+), 64 deletions(-)
---
diff --git a/tabbed.c b/tabbed.c
@@ -42,7 +42,7 @@
/* Macros */
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#define LENGTH(x) (sizeof (x) / sizeof *(x))
+#define LENGTH(x) (sizeof((x)) / sizeof(*(x)))
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask))
#define TEXTW(x) (textnw(x, strlen(x)) + dc.font.height)
@@ -201,10 +201,13 @@ cleanup(void) {
n = c->next;
unmanage(c);
}
- if(dc.font.set)
+
+ if(dc.font.set) {
XFreeFontSet(dpy, dc.font.set);
- else
+ } else {
XFreeFont(dpy, dc.font.xfont);
+ }
+
XFreePixmap(dpy, dc.drawable);
XFreeGC(dpy, dc.gc);
XDestroyWindow(dpy, win);
@@ -217,8 +220,9 @@ clientmessage(const XEvent *e) {
const XClientMessageEvent *ev = &e->xclient;
if(ev->message_type == wmatom[WMProtocols]
- && ev->data.l[0] == wmatom[WMDelete])
+ && ev->data.l[0] == wmatom[WMDelete]) {
running = False;
+ }
}
void
@@ -229,7 +233,8 @@ configurenotify(const XEvent *e) {
ww = ev->width;
wh = ev->height;
XFreePixmap(dpy, dc.drawable);
- dc.drawable = XCreatePixmap(dpy, root, ww, wh, DefaultDepth(dp…
+ dc.drawable = XCreatePixmap(dpy, root, ww, wh,
+ DefaultDepth(dpy, screen));
if(sel)
resize(sel, ww, wh - bh);
XSync(dpy, False);
@@ -297,10 +302,13 @@ drawbar() {
XSync(dpy, False);
return;
}
+
width = ww;
for(c = clients; c; c = c->next)
c->tabx = -1;
+
for(n = 0, fc = c = getfirsttab(); c; c = c->next, n++);
+
if(n * tabwidth > width) {
dc.w = TEXTW(after);
dc.x = width - dc.w;
@@ -308,22 +316,24 @@ drawbar() {
width -= dc.w;
}
dc.x = 0;
+
if(fc != clients) {
dc.w = TEXTW(before);
drawtext(before, dc.sel);
dc.x += dc.w;
width -= dc.w;
}
+
for(c = fc; c && dc.x < width; c = c->next) {
dc.w = tabwidth;
if(c == sel) {
col = dc.sel;
- if(n * tabwidth > width)
+ if(n * tabwidth > width) {
dc.w += width % tabwidth;
- else
+ } else {
dc.w = width - (n - 1) * tabwidth;
- }
- else {
+ }
+ } else {
col = dc.norm;
}
drawtext(c->name, col);
@@ -344,22 +354,30 @@ drawtext(const char *text, unsigned long col[ColLast]) {
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
if(!text)
return;
+
olen = strlen(text);
h = dc.font.ascent + dc.font.descent;
y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
x = dc.x + (h / 2);
+
/* shorten text if necessary */
- for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; …
+ for(len = MIN(olen, sizeof(buf));
+ len && textnw(text, len) > dc.w - h; len--);
if(!len)
return;
+
memcpy(buf, text, len);
- if(len < olen)
+ if(len < olen) {
for(i = len; i && i > len - 3; buf[--i] = '.');
+ }
+
XSetForeground(dpy, dc.gc, col[ColFG]);
- if(dc.font.set)
- XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf,…
- else
+ if(dc.font.set) {
+ XmbDrawString(dpy, dc.drawable, dc.font.set,
+ dc.gc, x, y, buf, len);
+ } else {
XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
+ }
}
void *
@@ -381,26 +399,31 @@ expose(const XEvent *e) {
void
focus(Client *c) {
+ char buf[BUFSIZ] = "tabbed-"VERSION" ::";
+ size_t i, n;
+
/* If c, sel and clients are NULL, raise tabbed-win itself */
if(!c && !(c = sel ? sel : clients)) {
- char buf[BUFSIZ] = "tabbed-"VERSION" ::";
- size_t i, n;
+ for(i = 0, n = strlen(buf); cmd[i] && n < sizeof(buf); i++)
+ n += snprintf(&buf[n], sizeof(buf) - n, " %s", cmd[i]);
- for(i = 0, n = strlen(buf); cmd[i] && n < sizeof buf; i++)
- n += snprintf(&buf[n], sizeof buf - n, " %s", cmd[i]);
XStoreName(dpy, win, buf);
XRaiseWindow(dpy, win);
+
return;
}
+
resize(c, ww, wh - bh);
XRaiseWindow(dpy, c->win);
XSetInputFocus(dpy, c->win, RevertToParent, CurrentTime);
sendxembed(c, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0);
sendxembed(c, XEMBED_WINDOW_ACTIVATE, 0, 0, 0);
XStoreName(dpy, win, c->name);
+
if(sel != c) {
lastsel = sel;
}
+
sel = c;
drawbar();
}
@@ -427,9 +450,11 @@ Client *
getclient(Window w) {
Client *c;
- for(c = clients; c; c = c->next)
+ for(c = clients; c; c = c->next) {
if(c->win == w)
return c;
+ }
+
return NULL;
}
@@ -440,6 +465,7 @@ getcolor(const char *colstr) {
if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
die("tabbed: cannot allocate color '%s'\n", colstr);
+
return color.pixel;
}
@@ -450,10 +476,13 @@ getfirsttab() {
if(!sel)
return NULL;
+
c = fc = clients;
for(n = 0; c; c = c->next, n++);
+
if(n * tabwidth > ww) {
for(seli = 0, c = clients; c && c != sel; c = c->next, seli++);
+
for(; seli * tabwidth > ww / 2 && n * tabwidth > ww;
fc = fc->next, seli--, n--);
}
@@ -468,40 +497,45 @@ gettextprop(Window w, Atom atom, char *text, unsigned int…
if(!text || size == 0)
return False;
+
text[0] = '\0';
XGetTextProperty(dpy, w, &name, atom);
if(!name.nitems)
return False;
- if(name.encoding == XA_STRING)
+
+ if(name.encoding == XA_STRING) {
strncpy(text, (char *)name.value, size - 1);
- else {
- if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success…
+ } else {
+ if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
+ && n > 0 && *list) {
strncpy(text, *list, size - 1);
XFreeStringList(list);
}
}
text[size - 1] = '\0';
XFree(name.value);
+
return True;
}
void
initfont(const char *fontstr) {
- char *def, **missing;
+ char *def, **missing, **font_names;
int i, n;
+ XFontStruct **xfonts;
missing = NULL;
if(dc.font.set)
XFreeFontSet(dpy, dc.font.set);
+
dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
if(missing) {
while(n--)
fprintf(stderr, "tabbed: missing fontset: %s\n", missi…
XFreeStringList(missing);
}
+
if(dc.font.set) {
- XFontStruct **xfonts;
- char **font_names;
dc.font.ascent = dc.font.descent = 0;
n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++…
@@ -509,14 +543,15 @@ initfont(const char *fontstr) {
dc.font.descent = MAX(dc.font.descent,(*xfonts)->desce…
xfonts++;
}
- }
- else {
+ } else {
if(dc.font.xfont)
XFreeFont(dpy, dc.font.xfont);
dc.font.xfont = NULL;
if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))
- && !(dc.font.xfont = XLoadQueryFont(dpy, "fixed")))
+ && !(dc.font.xfont = XLoadQueryFont(dpy, "fixe…
die("tabbed: cannot load font: '%s'\n", fontstr);
+ }
+
dc.font.ascent = dc.font.xfont->ascent;
dc.font.descent = dc.font.xfont->descent;
}
@@ -530,11 +565,13 @@ isprotodel(Client *c) {
Bool ret = False;
if(XGetWMProtocols(dpy, c->win, &protocols, &n)) {
- for(i = 0; !ret && i < n; i++)
+ for(i = 0; !ret && i < n; i++) {
if(protocols[i] == wmatom[WMDelete])
ret = True;
+ }
XFree(protocols);
}
+
return ret;
}
@@ -545,11 +582,13 @@ keypress(const XEvent *e) {
KeySym keysym;
keysym = XkbKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0, 0);
- for(i = 0; i < LENGTH(keys); i++)
+ for(i = 0; i < LENGTH(keys); i++) {
if(keysym == keys[i].keysym
- && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
- && keys[i].func)
+ && CLEANMASK(keys[i].mod) == CLEANMASK(ev->sta…
+ && keys[i].func) {
keys[i].func(&(keys[i].arg));
+ }
+ }
}
void
@@ -558,6 +597,7 @@ killclient(const Arg *arg) {
if(!sel)
return;
+
if(isprotodel(sel) && !sel->closed) {
ev.type = ClientMessage;
ev.xclient.window = sel->win;
@@ -567,9 +607,9 @@ killclient(const Arg *arg) {
ev.xclient.data.l[1] = CurrentTime;
XSendEvent(dpy, sel->win, False, NoEventMask, &ev);
sel->closed = True;
- }
- else
+ } else {
XKillClient(dpy, sel->win);
+ }
}
void
@@ -587,18 +627,22 @@ manage(Window w) {
XSelectInput(dpy, w, PropertyChangeMask|StructureNotifyMask|En…
XSync(dpy, False);
for(i = 0; i < LENGTH(keys); i++) {
- if((code = XKeysymToKeycode(dpy, keys[i].keysym)))
+ if((code = XKeysymToKeycode(dpy, keys[i].keysym))) {
for(j = 0; j < LENGTH(modifiers); j++)
XGrabKey(dpy, code, keys[i].mod | modi…
True, GrabModeAsync, GrabMode…
+ }
}
- c = emallocz(sizeof *c);
+
+ c = emallocz(sizeof(*c));
c->next = clients;
c->win = w;
clients = c;
+
updatetitle(c);
drawbar();
XMapRaised(dpy, w);
+
e.xclient.window = w;
e.xclient.type = ClientMessage;
e.xclient.message_type = wmatom[XEmbed];
@@ -609,9 +653,11 @@ manage(Window w) {
e.xclient.data.l[3] = win;
e.xclient.data.l[4] = 0;
XSendEvent(dpy, root, False, NoEventMask, &e);
+
XSync(dpy, False);
focus(nextfocus ? c : sel);
nextfocus = foreground;
+
if(!lastsel)
lastsel = c;
}
@@ -671,15 +717,15 @@ void
rotate(const Arg *arg) {
Client *c;
- if(arg->i == 0)
+ if(arg->i == 0) {
focus(lastsel);
- else if(arg->i > 0) {
- if(sel && sel->next)
+ } else if(arg->i > 0) {
+ if(sel && sel->next) {
focus(sel->next);
- else
+ } else {
focus(clients);
- }
- else {
+ }
+ } else {
for(c = clients; c && c->next && c->next != sel; c = c->next);
if(c)
focus(c);
@@ -695,6 +741,7 @@ run(void) {
drawbar();
if(doinitspawn == True)
spawn(NULL);
+
while(running) {
XNextEvent(dpy, &ev);
if(handler[ev.type])
@@ -722,7 +769,7 @@ void
setcmd(int argc, char *argv[]) {
int i;
- cmd = emallocz((argc+2) * sizeof *cmd);
+ cmd = emallocz((argc+2) * sizeof(*cmd));
for(i = 0; i < argc; i++)
cmd[i] = argv[i];
cmd[argc] = winid;
@@ -756,12 +803,14 @@ setup(void) {
dc.norm[ColFG] = getcolor(normfgcolor);
dc.sel[ColBG] = getcolor(selbgcolor);
dc.sel[ColFG] = getcolor(selfgcolor);
- dc.drawable = XCreatePixmap(dpy, root, ww, wh, DefaultDepth(dpy, scree…
+ dc.drawable = XCreatePixmap(dpy, root, ww, wh,
+ DefaultDepth(dpy, screen));
dc.gc = XCreateGC(dpy, root, 0, 0);
if(!dc.font.set)
XSetFont(dpy, dc.gc, dc.font.xfont->fid);
- win = XCreateSimpleWindow(dpy, root, wx, wy, ww, wh, 0, dc.norm[ColFG]…
+ win = XCreateSimpleWindow(dpy, root, wx, wy, ww, wh, 0,
+ dc.norm[ColFG], dc.norm[ColBG]);
XMapRaised(dpy, win);
XSelectInput(dpy, win, SubstructureNotifyMask|FocusChangeMask|
ButtonPressMask|ExposureMask|KeyPressMask|
@@ -775,7 +824,7 @@ setup(void) {
XSetWMProtocols(dpy, win, &wmatom[WMDelete], 1);
- snprintf(winid, sizeof winid, "%lu", win);
+ snprintf(winid, sizeof(winid), "%lu", win);
nextfocus = foreground;
focus(clients);
}
@@ -784,6 +833,7 @@ void
sigchld(int unused) {
if(signal(SIGCHLD, sigchld) == SIG_ERR)
die("tabbed: cannot install SIGCHLD handler");
+
while(0 < waitpid(-1, NULL, WNOHANG));
}
@@ -792,6 +842,7 @@ spawn(const Arg *arg) {
if(fork() == 0) {
if(dpy)
close(ConnectionNumber(dpy));
+
setsid();
if(arg && arg->v) {
execvp(((char **)arg->v)[0], (char **)arg->v);
@@ -813,6 +864,7 @@ textnw(const char *text, unsigned int len) {
XmbTextExtents(dc.font.set, text, len, NULL, &r);
return r.width;
}
+
return XTextWidth(dc.font.xfont, text, len);
}
@@ -820,11 +872,11 @@ void
unmanage(Client *c) {
Client *pc;
- if(!clients)
+ if(!clients) {
return;
- else if(c == clients)
+ } else if(c == clients) {
pc = clients = c->next;
- else {
+ } else {
for(pc = clients; pc && pc->next && pc->next != c; pc = pc->ne…
pc->next = c->next;
}
@@ -846,18 +898,21 @@ updatenumlockmask(void) {
numlockmask = 0;
modmap = XGetModifierMapping(dpy);
- for(i = 0; i < 8; i++)
- for(j = 0; j < modmap->max_keypermod; j++)
+ for(i = 0; i < 8; i++) {
+ for(j = 0; j < modmap->max_keypermod; j++) {
if(modmap->modifiermap[i * modmap->max_keypermod + j]
- == XKeysymToKeycode(dpy, XK_Num_Lock))
+ == XKeysymToKeycode(dpy, XK_Num_Lock))…
numlockmask = (1 << i);
+ }
+ }
+ }
XFreeModifiermap(modmap);
}
void
updatetitle(Client *c) {
- if(!gettextprop(c->win, wmatom[WMName], c->name, sizeof c->name))
- gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name);
+ if(!gettextprop(c->win, wmatom[WMName], c->name, sizeof(c->name)))
+ gettextprop(c->win, XA_WM_NAME, c->name, sizeof(c->name));
if(sel == c)
XStoreName(dpy, win, c->name);
drawbar();
@@ -869,15 +924,25 @@ updatetitle(Client *c) {
int
xerror(Display *dpy, XErrorEvent *ee) {
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 == BadDr…
- || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable)
- || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatc…
- || (ee->request_code == X_GrabButton && ee->error_code == BadAccess)
- || (ee->request_code == X_GrabKey && ee->error_code == BadAccess)
- || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable))
+ || (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_GrabButton
+ && ee->error_code == BadAccess)
+ || (ee->request_code == X_GrabKey
+ && ee->error_code == BadAccess)
+ || (ee->request_code == X_CopyArea
+ && ee->error_code == BadDrawable)) {
return 0;
+ }
+
fprintf(stderr, "tabbed: fatal error: request code=%d, error code=%d\n…
ee->request_code, ee->error_code);
return xerrorxlib(dpy, ee); /* may call exit */
@@ -886,8 +951,7 @@ xerror(Display *dpy, XErrorEvent *ee) {
char *argv0;
void
-usage(void)
-{
+usage(void) {
die("usage: %s [-dhsv] [-n name] command...\n", argv0);
}
@@ -923,6 +987,7 @@ main(int argc, char *argv[]) {
fprintf(stderr, "tabbed: no locale support\n");
if(!(dpy = XOpenDisplay(NULL)))
die("tabbed: cannot open display\n");
+
setup();
printf("0x%lx\n", win);
fflush(NULL);
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.