tabbed

Simple tabbing application for X11.
git clone git://r-36.net/tabbed
Log | Files | Refs | README | LICENSE

commit 92571a0887b28bb17f40d3352a6b8f2526575298
parent ef13e9be81e52c845314a49b2ac77690b8a35429
Author: Enno Boland (tox) <tox@s01.de>
Date:   Tue,  8 Sep 2009 00:06:46 +0200

implementing spawntab(), rewriting run()
Diffstat:
config.def.h | 6+++---
tabbed.c | 113++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
2 files changed, 98 insertions(+), 21 deletions(-)

diff --git a/config.def.h b/config.def.h @@ -3,13 +3,13 @@ static const char normbgcolor[] = "#202020"; static const char normfgcolor[] = "#c0c0c0"; static const char selbgcolor[] = "#884400"; static const char selfgcolor[] = "#f0f0f0"; -static const char *surfexec[] = { "surf", "-x" }; +#define SURF "surf", "-x" #define MODKEY ControlMask Key keys[] = { \ /* modifier key function argument */ - { MODKEY|ShiftMask, XK_Return, newtab, { 0 } }, - { MODKEY, XK_t, newtab, { 0 } }, + { MODKEY|ShiftMask, XK_Return, spawntab, { .v = (char*[]){ SURF, NULL} } }, + { MODKEY|ShiftMask, XK_t, spawntab, { .v = (char*[]){ SURF, NULL} } }, { MODKEY|ShiftMask, XK_l, rotate, { .i = +1 } }, { MODKEY|ShiftMask, XK_h, rotate, { .i = -1 } }, { MODKEY, XK_1, move, { .i = 1 } }, diff --git a/tabbed.c b/tabbed.c @@ -2,22 +2,26 @@ * * To understand tabbed, start reading main(). */ +#include <sys/select.h> +#include <sys/types.h> +#include <sys/wait.h> #include <locale.h> #include <stdarg.h> +#include <unistd.h> +#include <signal.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <X11/keysym.h> #include <X11/Xatom.h> #include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xproto.h> -#include <X11/extensions/XTest.h> +#include <errno.h> /* macros */ #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define LENGTH(x) (sizeof x / sizeof x[0]) #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask)) +#define TEXTW(x) (textnw(x, strlen(x)) + dc.font.height) enum { ColFG, ColBG, ColLast }; /* color */ @@ -72,7 +76,7 @@ static void initfont(const char *fontstr); static void keypress(XEvent *e); static void killclient(const Arg *arg); static void move(const Arg *arg); -static void newtab(const Arg *arg); +static void spawntab(const Arg *arg); static void rotate(const Arg *arg); static void run(void); static void setup(void); @@ -93,15 +97,12 @@ static DC dc; static Window root, win; static Bool running = True; static unsigned int numlockmask = 0; +Client *clients, *sel; +Listener *listeners; /* configuration, allows nested code to access above variables */ #include "config.h" void -buttonrelease(XEvent *e) { - //XButtonPressedEvent *ev = &e->xbutton; -} - -void cleanup(void) { if(dc.font.set) XFreeFontSet(dpy, dc.font.set); @@ -136,9 +137,13 @@ die(const char *errstr, ...) { exit(EXIT_FAILURE); } -void -unmapnotify(XEvent *e) { - running = False; +void * +emallocz(size_t size) { + void *p; + + if(!(p = calloc(1, size))) + die(0, "Cannot Malloc"); + return p; } void @@ -222,8 +227,36 @@ move(const Arg *arg) { } void -newtab(const Arg *arg) { - puts("opening new tab"); +sigchld(int signal) { + while(0 < waitpid(-1, NULL, WNOHANG)); +} + +void +spawntab(const Arg *arg) { + int fd[2]; + Listener *l; + + if(pipe(fd)) { + perror("tabbed: pipe failed"); + return; + } + l = emallocz(sizeof(Listener)); + l->fd = fd[0]; + l->next = listeners; + listeners = l; + signal(SIGCHLD, sigchld); + if(fork() == 0) { + if(dpy) + close(ConnectionNumber(dpy)); + setsid(); + dup2(fd[1], STDOUT_FILENO); + close(fd[0]); + execvp(((char **)arg->v)[0], (char **)arg->v); + fprintf(stderr, "tabbed: execvp %s", ((char **)arg->v)[0]); + perror(" failed"); + exit(0); + } + close(fd[1]); } void @@ -233,13 +266,52 @@ rotate(const Arg *arg) { void run(void) { + char buf[32], *p; + fd_set rd; + int r, xfd; + unsigned int offset; XEvent ev; + Listener *l; + /* main event loop, also reads status text from stdin */ XSync(dpy, False); + xfd = ConnectionNumber(dpy); + buf[LENGTH(buf) - 1] = '\0'; /* 0-terminator is never touched */ while(running) { - XNextEvent(dpy, &ev); - if(handler[ev.type]) - (handler[ev.type])(&ev); /* call handler */ + FD_ZERO(&rd); + for(l = listeners; l; l = l->next) { + printf("setting %i\n", l->fd); + FD_SET(l->fd, &rd); + } + FD_SET(xfd, &rd); + if(select(xfd + 1, &rd, NULL, NULL, NULL) == -1) { + if(errno == EINTR) + continue; + die("select failed\n"); + } + for(l = listeners; l; l = l->next) { + printf("testing %i\n", l->fd); + if(!FD_ISSET(l->fd, &rd)) + continue; + switch((r = read(l->fd, buf + offset, LENGTH(buf) - 1 - offset))) { + case -1: + case 0: + break; + default: + for(p = buf + offset; r > 0; p++, r--, offset++) + if(*p == '\n' || *p == '\0') { + *p = '\0'; + printf("Got somthing: %s\n", buf); + break; + } + break; + } + } + while(XPending(dpy)) { + XNextEvent(dpy, &ev); + if(handler[ev.type]) + (handler[ev.type])(&ev); /* call handler */ + } } } @@ -283,6 +355,11 @@ textnw(const char *text, unsigned int len) { } void +unmapnotify(XEvent *e) { + running = False; +} + +void updatenumlockmask(void) { unsigned int i, j; XModifierKeymap *modmap; @@ -313,6 +390,6 @@ main(int argc, char *argv[]) { cleanup(); XCloseDisplay(dpy); return 0; - textnw(surfexec[0], strlen(surfexec[0])); + textnw(" ", 1); updatenumlockmask(); }