tabbed

tab interface for application supporting Xembed
git clone git://git.suckless.org/tabbed
Log | Files | Refs | README | LICENSE

commit aa5f91e0d54333e4da247528f5eacb721710d16d
parent 77aac73c1e88d840dc9a8b07f2c02b5cb8553835
Author: Enno Boland (tox) <tox@s01.de>
Date:   Mon,  7 Sep 2009 13:32:58 +0200

adding sourcecode.
Diffstat:
Atabbed.c | 317+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 317 insertions(+), 0 deletions(-)

diff --git a/tabbed.c b/tabbed.c @@ -0,0 +1,317 @@ +/* See LICENSE file for copyright and license details. + * + * To understand tabbed, start reading main(). + */ +#include <locale.h> +#include <stdarg.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> + +/* macros */ +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define LENGTH(x) (sizeof x / sizeof x[0]) +#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask)) + +enum { ColFG, ColBG, ColLast }; /* color */ + +typedef union { + int i; + unsigned int ui; + float f; + const void *v; +} Arg; + +typedef struct { + unsigned int mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; +} Key; + +typedef struct { + int x, y, w, h; + unsigned long norm[ColLast]; + unsigned long sel[ColLast]; + Drawable drawable; + GC gc; + struct { + int ascent; + int descent; + int height; + XFontSet set; + XFontStruct *xfont; + } font; +} DC; /* draw context */ + +typedef struct Client Client; +struct Client { + char name[256]; + struct Client *next; + Window win; +}; + +/* function declarations */ +static void cleanup(void); +static void configurenotify(XEvent *e); +static void unmapnotify(XEvent *e); +static void die(const char *errstr, ...); +static void expose(XEvent *e); +static unsigned long getcolor(const char *colstr); +static void initfont(const char *fontstr); +static void keypress(XEvent *e); +static void move(const Arg *arg); +static void newtab(const Arg *arg); +static void rotate(const Arg *arg); +static void run(void); +static void setup(void); +static int textnw(const char *text, unsigned int len); +static void updatenumlockmask(void); + +/* variables */ +static int screen; +static int wx, wy, ww, wh; +static void (*handler[LASTEvent]) (XEvent *) = { + [ConfigureNotify] = configurenotify, + [UnmapNotify] = unmapnotify, + [KeyPress] = keypress, + [Expose] = expose, +}; +static Display *dpy; +static DC dc; +static Window root, win; +static Bool running = True; +static unsigned int numlockmask = 0; +/* configuration, allows nested code to access above variables */ +#define TABBED +#include "config.h" + +void +buttonrelease(XEvent *e) { + //XButtonPressedEvent *ev = &e->xbutton; +} + +void +cleanup(void) { + if(dc.font.set) + XFreeFontSet(dpy, dc.font.set); + else + XFreeFont(dpy, dc.font.xfont); + XFreePixmap(dpy, dc.drawable); + XFreeGC(dpy, dc.gc); + XDestroyWindow(dpy, win); + XSync(dpy, False); + XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); +} + +void +configurenotify(XEvent *e) { + XConfigureEvent *ev = &e->xconfigure; + + if(ev->window == win && (ev->width != ww || ev->height != wh)) { + ww = ev->width; + wh = ev->height; + XFreePixmap(dpy, dc.drawable); + dc.drawable = XCreatePixmap(dpy, root, ww, wh, DefaultDepth(dpy, screen)); + } +} + +void +die(const char *errstr, ...) { + va_list ap; + + va_start(ap, errstr); + vfprintf(stderr, errstr, ap); + va_end(ap); + exit(EXIT_FAILURE); +} + +void +unmapnotify(XEvent *e) { + running = False; +} + +void +expose(XEvent *e) { + /*XExposeEvent *ev = &e->xexpose;*/ +} + +unsigned long +getcolor(const char *colstr) { + Colormap cmap = DefaultColormap(dpy, screen); + XColor color; + + if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) + die("error, cannot allocate color '%s'\n", colstr); + return color.pixel; +} + +void +initfont(const char *fontstr) { + char *def, **missing; + int i, n; + + 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", missing[n]); + XFreeStringList(missing); + } + if(dc.font.set) { + XFontSetExtents *font_extents; + XFontStruct **xfonts; + char **font_names; + dc.font.ascent = dc.font.descent = 0; + font_extents = XExtentsOfFontSet(dc.font.set); + n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); + for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) { + dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent); + dc.font.descent = MAX(dc.font.descent,(*xfonts)->descent); + xfonts++; + } + } + 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"))) + die("error, cannot load font: '%s'\n", fontstr); + dc.font.ascent = dc.font.xfont->ascent; + dc.font.descent = dc.font.xfont->descent; + } + dc.font.height = dc.font.ascent + dc.font.descent; +} + +void +keypress(XEvent *e) { + unsigned int i; + KeySym keysym; + XKeyEvent *ev; + + ev = &e->xkey; + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); + for(i = 0; i < LENGTH(keys); i++) + if(keysym == keys[i].keysym + && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) + && keys[i].func) + keys[i].func(&(keys[i].arg)); +} + +void +move(const Arg *arg) { + +} + +void +newtab(const Arg *arg) { + +} + +void +rotate(const Arg *arg) { + +} + +void +run(void) { + XEvent ev; + + /* main event loop, also reads status text from stdin */ + XSync(dpy, False); + while(running) { + XNextEvent(dpy, &ev); + if(handler[ev.type]) + (handler[ev.type])(&ev); /* call handler */ + } +} + +void +setup(void) { + XWMHints *wmh; + + /* init screen */ + screen = DefaultScreen(dpy); + root = RootWindow(dpy, screen); + initfont(font); + + /* init appearance */ + wx = 0; + wy = 0; + ww = 800; + wh = 600; + dc.norm[ColBG] = getcolor(normbgcolor); + dc.norm[ColFG] = getcolor(normfgcolor); + dc.sel[ColBG] = getcolor(selbgcolor); + dc.sel[ColFG] = getcolor(selfgcolor); + 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], dc.norm[ColBG]); + XSelectInput(dpy, win, StructureNotifyMask|PointerMotionMask| + ButtonReleaseMask|ButtonPressMask|ExposureMask| + LeaveWindowMask); + wmh = XAllocWMHints(); + wmh->input = False; + wmh->flags = InputHint; + XSetWMHints(dpy, win, wmh); + XFree(wmh); + XMapRaised(dpy, win); +} + +int +textnw(const char *text, unsigned int len) { + XRectangle r; + + if(dc.font.set) { + XmbTextExtents(dc.font.set, text, len, NULL, &r); + return r.width; + } + return XTextWidth(dc.font.xfont, text, len); +} + +void +updatenumlockmask(void) { + unsigned int i, j; + XModifierKeymap *modmap; + + numlockmask = 0; + modmap = XGetModifierMapping(dpy); + 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)) + numlockmask = (1 << i); + XFreeModifiermap(modmap); +} + +int +main(int argc, char *argv[]) { + if(argc == 2 && !strcmp("-v", argv[1])) + die("tabbed-"VERSION", © 2006-2008 surf engineers, see LICENSE for details\n"); + else if(argc != 1) + die("usage: tabbed [surf-options]\n"); + if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) + fprintf(stderr, "warning: no locale support\n"); + if(!(dpy = XOpenDisplay(0))) + die("tabbed: cannot open display\n"); + setup(); + run(); + /*dummys*/ + cleanup(); + XCloseDisplay(dpy); + return 0; + textnw(surfexec[0], strlen(surfexec[0])); + updatenumlockmask(); +}