diff options
Diffstat (limited to 'utils')
| -rw-r--r-- | utils/tabbed/LICENSE | 23 | ||||
| -rw-r--r-- | utils/tabbed/Makefile | 60 | ||||
| -rw-r--r-- | utils/tabbed/README | 22 | ||||
| -rw-r--r-- | utils/tabbed/TODO | 4 | ||||
| -rw-r--r-- | utils/tabbed/arg.h | 52 | ||||
| -rw-r--r-- | utils/tabbed/config.def.h | 58 | ||||
| -rw-r--r-- | utils/tabbed/config.h | 56 | ||||
| -rw-r--r-- | utils/tabbed/config.mk | 25 | ||||
| -rw-r--r-- | utils/tabbed/tabbed.1 | 144 | ||||
| -rw-r--r-- | utils/tabbed/tabbed.c | 1297 |
10 files changed, 0 insertions, 1741 deletions
diff --git a/utils/tabbed/LICENSE b/utils/tabbed/LICENSE deleted file mode 100644 index add8a53..0000000 --- a/utils/tabbed/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -MIT/X Consortium License - -© 2009-2011 Enno Boland <g s01 de> -© 2011 Connor Lane Smith <cls@lubutu.com> -© 2012 Christoph Lohmann <20h@r-36.net> - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/utils/tabbed/Makefile b/utils/tabbed/Makefile deleted file mode 100644 index 32cc25b..0000000 --- a/utils/tabbed/Makefile +++ /dev/null @@ -1,60 +0,0 @@ -# tabbed - tabbing interface -# See LICENSE file for copyright and license details. - -include config.mk - -SRC = tabbed.c -OBJ = ${SRC:.c=.o} - -all: options tabbed - -options: - @echo tabbed build options: - @echo "CFLAGS = ${CFLAGS}" - @echo "LDFLAGS = ${LDFLAGS}" - @echo "CC = ${CC}" - -.c.o: - @echo CC $< - @${CC} -c ${CFLAGS} $< - -${OBJ}: config.h config.mk - -config.h: - @echo creating $@ from config.def.h - @cp config.def.h $@ - -tabbed: tabbed.o - @echo CC -o $@ - @${CC} -o $@ tabbed.o ${LDFLAGS} - -clean: - @echo cleaning - @rm -f tabbed ${OBJ} tabbed-${VERSION}.tar.gz - -dist: clean - @echo creating dist tarball - @mkdir -p tabbed-${VERSION} - @cp -R LICENSE Makefile README config.def.h config.mk \ - tabbed.1 arg.h ${SRC} tabbed-${VERSION} - @tar -cf tabbed-${VERSION}.tar tabbed-${VERSION} - @gzip tabbed-${VERSION}.tar - @rm -rf tabbed-${VERSION} - -install: all - @echo installing executable file to ${DESTDIR}${PREFIX}/bin - @mkdir -p ${DESTDIR}${PREFIX}/bin - @cp -f tabbed ${DESTDIR}${PREFIX}/bin - @chmod 755 ${DESTDIR}${PREFIX}/bin/tabbed - @echo installing manual page to ${DESTDIR}${MANPREFIX}/man1 - @mkdir -p ${DESTDIR}${MANPREFIX}/man1 - @sed "s/VERSION/${VERSION}/g" < tabbed.1 > ${DESTDIR}${MANPREFIX}/man1/tabbed.1 - @chmod 644 ${DESTDIR}${MANPREFIX}/man1/tabbed.1 - -uninstall: - @echo removing executable file from ${DESTDIR}${PREFIX}/bin - @rm -f ${DESTDIR}${PREFIX}/bin/tabbed - @echo removing manual page from ${DESTDIR}${MANPREFIX}/man1 - @rm -f ${DESTDIR}${MANPREFIX}/man1/tabbed.1 - -.PHONY: all options clean dist install uninstall diff --git a/utils/tabbed/README b/utils/tabbed/README deleted file mode 100644 index 4ed6bbe..0000000 --- a/utils/tabbed/README +++ /dev/null @@ -1,22 +0,0 @@ -tabbed - generic tabbed interface -================================= -tabbed is a simple tabbed X window container. - -Requirements ------------- -In order to build tabbed you need the Xlib header files. - -Installation ------------- -Edit config.mk to match your local setup (tabbed is installed into -the /usr/local namespace by default). - -Afterwards enter the following command to build and install tabbed -(if necessary as root): - - make clean install - -Running tabbed --------------- -See the man page for details. - diff --git a/utils/tabbed/TODO b/utils/tabbed/TODO deleted file mode 100644 index 8e1986d..0000000 --- a/utils/tabbed/TODO +++ /dev/null @@ -1,4 +0,0 @@ -# TODO -* add some way to detach windows -* add some way to attach windows - diff --git a/utils/tabbed/arg.h b/utils/tabbed/arg.h deleted file mode 100644 index a345b0b..0000000 --- a/utils/tabbed/arg.h +++ /dev/null @@ -1,52 +0,0 @@ -/* See the LICENSE file for copyright and license details. */ - -#ifndef __ARG_H__ -#define __ARG_H__ - -extern char *argv0; - -#define USED(x) ((void)(x)) - -/* use main(int argc, char *argv[]) */ -#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ - argv[0] && argv[0][1]\ - && argv[0][0] == '-';\ - argc--, argv++) {\ - char _argc;\ - char **_argv;\ - int brk;\ - if (argv[0][1] == '-' && argv[0][2] == '\0') {\ - argv++;\ - argc--;\ - break;\ - }\ - for (brk = 0, argv[0]++, _argv = argv;\ - argv[0][0] && !brk;\ - argv[0]++) {\ - if (_argv != argv)\ - break;\ - _argc = argv[0][0];\ - switch (_argc) - -#define ARGEND }\ - USED(_argc);\ - }\ - USED(argv);\ - USED(argc); - -#define ARGC() _argc - -#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\ - ((x), abort(), (char *)0) :\ - (brk = 1, (argv[0][1] != '\0')?\ - (&argv[0][1]) :\ - (argc--, argv++, argv[0]))) - -#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\ - (char *)0 :\ - (brk = 1, (argv[0][1] != '\0')?\ - (&argv[0][1]) :\ - (argc--, argv++, argv[0]))) - -#endif - diff --git a/utils/tabbed/config.def.h b/utils/tabbed/config.def.h deleted file mode 100644 index ceda9f7..0000000 --- a/utils/tabbed/config.def.h +++ /dev/null @@ -1,58 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* appearance */ -static const char font[] = "-*-*-medium-*-*-*-14-*-*-*-*-*-*-*"; -static const char* normbgcolor = "#222222"; -static const char* normfgcolor = "#cccccc"; -static const char* selbgcolor = "#555555"; -static const char* selfgcolor = "#ffffff"; -static const char before[] = "<"; -static const char after[] = ">"; -static const int tabwidth = 200; -static const Bool foreground = True; - -/* - * Where to place a new tab when it is opened. When npisrelative is True, - * then the current position is changed + newposition. If npisrelative - * is False, then newposition is an absolute position. - */ -static int newposition = 0; -static Bool npisrelative = False; - -#define SETPROP(p) { \ - .v = (char *[]){ "/bin/sh", "-c", \ - "prop=\"`xwininfo -children -id $1 | grep '^ 0x' | sed -e's@^ *\\(0x[0-9a-f]*\\) \"\\([^\"]*\\)\".*@\\1 \\2@' | xargs -0 printf %b | dmenu -l 10`\" &&" \ - "xprop -id $1 -f $0 8s -set $0 \"$prop\"", \ - p, winid, NULL \ - } \ -} - -#define MODKEY ControlMask -static Key keys[] = { \ - /* modifier key function argument */ - { MODKEY|ShiftMask, XK_Return, focusonce, { 0 } }, - { MODKEY|ShiftMask, XK_Return, spawn, { 0 } }, - { MODKEY, XK_t, spawn, SETPROP("_TABBED_SELECT_TAB") }, - - { MODKEY|ShiftMask, XK_l, rotate, { .i = +1 } }, - { MODKEY|ShiftMask, XK_h, rotate, { .i = -1 } }, - { MODKEY|ShiftMask, XK_j, movetab, { .i = -1 } }, - { MODKEY|ShiftMask, XK_k, movetab, { .i = +1 } }, - { MODKEY, XK_Tab, rotate, { .i = 0 } }, - - { MODKEY, XK_1, move, { .i = 0 } }, - { MODKEY, XK_2, move, { .i = 1 } }, - { MODKEY, XK_3, move, { .i = 2 } }, - { MODKEY, XK_4, move, { .i = 3 } }, - { MODKEY, XK_5, move, { .i = 4 } }, - { MODKEY, XK_6, move, { .i = 5 } }, - { MODKEY, XK_7, move, { .i = 6 } }, - { MODKEY, XK_8, move, { .i = 7 } }, - { MODKEY, XK_9, move, { .i = 8 } }, - { MODKEY, XK_0, move, { .i = 9 } }, - - { MODKEY, XK_q, killclient, { 0 } }, - - { 0, XK_F11, fullscreen, { 0 } }, -}; - diff --git a/utils/tabbed/config.h b/utils/tabbed/config.h deleted file mode 100644 index 0ead353..0000000 --- a/utils/tabbed/config.h +++ /dev/null @@ -1,56 +0,0 @@ -#include "../../colors.h" -/* See LICENSE file for copyright and license details. */ - -/* appearance */ -/*static const char font[] = "-*-*-medium-*-*-*-14-*-*-*-*-*-*-*"; */ -static const char font[] = "Source Code Pro:size=9"; -static const char before[] = "<"; -static const char after[] = ">"; -static const int tabwidth = 200; -static const Bool foreground = True; - -/* - * Where to place a new tab when it is opened. When npisrelative is True, - * then the current position is changed + newposition. If npisrelative - * is False, then newposition is an absolute position. - */ -static int newposition = 0; -static Bool npisrelative = False; - -#define SETPROP(p) { \ - .v = (char *[]){ "/bin/sh", "-c", \ - "prop=\"`xwininfo -children -id $1 | grep '^ 0x' | sed -e's@^ *\\(0x[0-9a-f]*\\) \"\\([^\"]*\\)\".*@\\1 \\2@' | xargs -0 printf %b | dmenu -l 10`\" &&" \ - "xprop -id $1 -f $0 8s -set $0 \"$prop\"", \ - p, winid, NULL \ - } \ -} - -#define MODKEY ControlMask -static Key keys[] = { \ - /* modifier key function argument */ - { MODKEY|ShiftMask, XK_Return, focusonce, { 0 } }, - { MODKEY|ShiftMask, XK_Return, spawn, { 0 } }, - { MODKEY, XK_t, spawn, SETPROP("_TABBED_SELECT_TAB") }, - - { MODKEY|ShiftMask, XK_l, rotate, { .i = +1 } }, - { MODKEY|ShiftMask, XK_h, rotate, { .i = -1 } }, - { MODKEY|ShiftMask, XK_j, movetab, { .i = -1 } }, - { MODKEY|ShiftMask, XK_k, movetab, { .i = +1 } }, - { MODKEY, XK_Tab, rotate, { .i = 0 } }, - - { MODKEY, XK_1, move, { .i = 0 } }, - { MODKEY, XK_2, move, { .i = 1 } }, - { MODKEY, XK_3, move, { .i = 2 } }, - { MODKEY, XK_4, move, { .i = 3 } }, - { MODKEY, XK_5, move, { .i = 4 } }, - { MODKEY, XK_6, move, { .i = 5 } }, - { MODKEY, XK_7, move, { .i = 6 } }, - { MODKEY, XK_8, move, { .i = 7 } }, - { MODKEY, XK_9, move, { .i = 8 } }, - { MODKEY, XK_0, move, { .i = 9 } }, - - { MODKEY, XK_q, killclient, { 0 } }, - - { 0, XK_F11, fullscreen, { 0 } }, -}; - diff --git a/utils/tabbed/config.mk b/utils/tabbed/config.mk deleted file mode 100644 index 426c93b..0000000 --- a/utils/tabbed/config.mk +++ /dev/null @@ -1,25 +0,0 @@ -include ../../config.mk -# tabbed version -VERSION = 0.6 - -# Customize below to fit your system - -# paths -MANPREFIX = ${PREFIX}/share/man - -# includes and libs -INCS = -I. -I/usr/include -LIBS = -L/usr/lib -lc -lX11 - -# flags -CPPFLAGS = -DVERSION=\"${VERSION}\" -D_BSD_SOURCE -CFLAGS = -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -LDFLAGS = -s ${LIBS} - -# Solaris -#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" -#LDFLAGS = ${LIBS} - -# compiler and linker -CC = cc - diff --git a/utils/tabbed/tabbed.1 b/utils/tabbed/tabbed.1 deleted file mode 100644 index 0ae29ce..0000000 --- a/utils/tabbed/tabbed.1 +++ /dev/null @@ -1,144 +0,0 @@ -.TH TABBED 1 tabbed\-VERSION -.SH NAME -tabbed \- generic tabbed interface -.SH SYNOPSIS -.B tabbed -.RB [ \-c ] -.RB [ \-d ] -.RB [ \-h ] -.RB [ \-s ] -.RB [ \-v ] -.RB [ \-g -.IR geometry ] -.RB [ \-n -.IR name ] -.RB [ \-p -.IR [ s +/- ] pos ] -.RB [ \-r -.IR narg ] -.IR [ command ... ] -.SH DESCRIPTION -.B tabbed -is a simple tabbed container for applications which support XEmbed. Tabbed -will then run the provided command with the xid of tabbed as appended -argument. (See EXAMPLES.) The automatic spawning of the command can be -disabled by providing the -s parameter. If no command is provided -tabbed will just print its xid and run no command. -.SH OPTIONS -.TP -.B \-c -close tabbed when the last tab is closed. Mutually exclusive with -f. -.TP -.B \-d -detaches tabbed from the terminal and prints its XID to stdout. -.TP -.B \-f -fill up tabbed again by spawning the provided command, when the last tab is -closed. Mutually exclusive with -c. -.TP -.B \-h -will print the usage of tabbed. -.TP -.BI \-g " geometry" -defines the X11 geometry string, which will fixate the height and width of -tabbed. -Them form is [=][<width>{xX}<height>][{+-}<xoffset>{+-}<yoffset>]. See -.BR XParseGeometry (3) -for further details. -.TP -.BI \-n " name" -will set the WM_CLASS attribute to -.I name. -.TP -.BI \-p " [ s +/-] pos" -will set the absolute or relative position of where to start a new tab. When -.I pos -is is given without 's' in front it is an absolute position. Then negative -numbers will be the position from the last tab, where -1 is the last tab. -If 's' is given, then -.I pos -is a relative position to the current selected tab. If this reaches the limits -of the tabs; those limits then apply. -.TP -.BI \-r " narg" -will replace the -.I narg -th argument in -.I command -with the window id, rather than appending it to the end. -.TP -.B \-s -will disable automatic spawning of the command. -.TP -.BI \-t " color" -defines the selected background color. -.IR #RGB , -.IR #RRGGBB , -and X color names are supported. -.TP -.BI \-T " color" -defines the selected foreground color. -.TP -.BI \-u " color" -defines the normal background color. -.TP -.BI \-U " color" -defines the normal foreground color. -.TP -.B \-v -prints version information to stderr, then exits. -.SH USAGE -.TP -.B Ctrl\-Shift\-Return -open new tab -.TP -.B Ctrl\-Shift\-h -previous tab -.TP -.B Ctrl\-Shift\-l -next tab -.TP -.B Ctrl\-Shift\-j -move selected tab one to the left -.TP -.B Ctrl\-Shift\-k -move selected tab one to the right -.TP -.B Ctrl\-Tab -toggle between the selected and last selected tab -.TP -.B Ctrl\-t -open dmenu to either create a new tab appending the entered string or select -an already existing tab. -.TP -.B Ctrl\-q -close tab -.TP -.B Ctrl\-[0..9] -jumps to nth tab -.TP -.B F11 -Toggle fullscreen mode. -.SH EXAMPLES -$ tabbed surf -e -.TP -$ tabbed urxvt -embed -.TP -$ tabbed xterm -into -.TP -$ $(tabbed -d >/tmp/tabbed.xid); urxvt -embed $(</tmp/tabbed.xid); -.TP -$ tabbed -r 2 st -w '' -e tmux -.SH CUSTOMIZATION -.B tabbed -can be customized by creating a custom config.h and (re)compiling the source -code. This keeps it fast, secure and simple. -.SH AUTHORS -See the LICENSE file for the authors. -.SH LICENSE -See the LICENSE file for the terms of redistribution. -.SH SEE ALSO -.BR st (1) -.SH BUGS -Please report them. - diff --git a/utils/tabbed/tabbed.c b/utils/tabbed/tabbed.c deleted file mode 100644 index d30206b..0000000 --- a/utils/tabbed/tabbed.c +++ /dev/null @@ -1,1297 +0,0 @@ -/* - * See LICENSE file for copyright and license details. - */ - -#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/Xatom.h> -#include <X11/Xlib.h> -#include <X11/Xproto.h> -#include <X11/Xutil.h> -#include <X11/XKBlib.h> - -#include "arg.h" - -/* XEMBED messages */ -#define XEMBED_EMBEDDED_NOTIFY 0 -#define XEMBED_WINDOW_ACTIVATE 1 -#define XEMBED_WINDOW_DEACTIVATE 2 -#define XEMBED_REQUEST_FOCUS 3 -#define XEMBED_FOCUS_IN 4 -#define XEMBED_FOCUS_OUT 5 -#define XEMBED_FOCUS_NEXT 6 -#define XEMBED_FOCUS_PREV 7 -/* 8-9 were used for XEMBED_GRAB_KEY/XEMBED_UNGRAB_KEY */ -#define XEMBED_MODALITY_ON 10 -#define XEMBED_MODALITY_OFF 11 -#define XEMBED_REGISTER_ACCELERATOR 12 -#define XEMBED_UNREGISTER_ACCELERATOR 13 -#define XEMBED_ACTIVATE_ACCELERATOR 14 - -/* Details for XEMBED_FOCUS_IN: */ -#define XEMBED_FOCUS_CURRENT 0 -#define XEMBED_FOCUS_FIRST 1 -#define XEMBED_FOCUS_LAST 2 - -/* 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 CLEANMASK(mask) (mask & ~(numlockmask|LockMask)) -#define TEXTW(x) (textnw(x, strlen(x)) + dc.font.height) - -enum { ColFG, ColBG, ColLast }; /* color */ -enum { WMProtocols, WMDelete, WMName, WMState, WMFullscreen, - XEmbed, WMSelectTab, WMLast }; /* default atoms */ - -typedef union { - int i; - 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 { - char name[256]; - Window win; - int tabx; - Bool mapped; - Bool closed; -} Client; - -/* function declarations */ -static void buttonpress(const XEvent *e); -static void cleanup(void); -static void clientmessage(const XEvent *e); -static void configurenotify(const XEvent *e); -static void configurerequest(const XEvent *e); -static void createnotify(const XEvent *e); -static void destroynotify(const XEvent *e); -static void die(const char *errstr, ...); -static void drawbar(void); -static void drawtext(const char *text, unsigned long col[ColLast]); -static void *emallocz(size_t size); -static void *erealloc(void *o, size_t size); -static void expose(const XEvent *e); -static void focus(int c); -static void focusin(const XEvent *e); -static void focusonce(const Arg *arg); -static void fullscreen(const Arg *arg); -static char* getatom(int a); -static int getclient(Window w); -static unsigned long getcolor(const char *colstr); -static int getfirsttab(void); -static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); -static void initfont(const char *fontstr); -static Bool isprotodel(int c); -static void keypress(const XEvent *e); -static void killclient(const Arg *arg); -static void manage(Window win); -static void maprequest(const XEvent *e); -static void move(const Arg *arg); -static void movetab(const Arg *arg); -static void propertynotify(const XEvent *e); -static void resize(int c, int w, int h); -static void rotate(const Arg *arg); -static void run(void); -static void sendxembed(int c, long msg, long detail, long d1, long d2); -static void setup(void); -static void setcmd(int argc, char *argv[], int); -static void sigchld(int unused); -static void spawn(const Arg *arg); -static int textnw(const char *text, unsigned int len); -static void unmanage(int c); -static void updatenumlockmask(void); -static void updatetitle(int c); -static int xerror(Display *dpy, XErrorEvent *ee); -static void xsettitle(Window w, const char *str); - -/* variables */ -static int screen; -static void (*handler[LASTEvent]) (const XEvent *) = { - [ButtonPress] = buttonpress, - [ClientMessage] = clientmessage, - [ConfigureNotify] = configurenotify, - [ConfigureRequest] = configurerequest, - [CreateNotify] = createnotify, - [DestroyNotify] = destroynotify, - [Expose] = expose, - [FocusIn] = focusin, - [KeyPress] = keypress, - [MapRequest] = maprequest, - [PropertyNotify] = propertynotify, -}; -static int bh, wx, wy, ww, wh; -static unsigned int numlockmask = 0; -static Bool running = True, nextfocus, doinitspawn = True, - fillagain = False, closelastclient = False; -static Display *dpy; -static DC dc; -static Atom wmatom[WMLast]; -static Window root, win; -static Client **clients = NULL; -static int nclients = 0, sel = -1, lastsel = -1; -static int (*xerrorxlib)(Display *, XErrorEvent *); -static int cmd_append_pos = 0; -static char winid[64]; -static char **cmd = NULL; -static char *wmname = "tabbed"; -static const char *geometry = NULL; - -char *argv0; - -/* configuration, allows nested code to access above variables */ -#include "config.h" - -void -buttonpress(const XEvent *e) { - const XButtonPressedEvent *ev = &e->xbutton; - int i; - int fc; - Arg arg; - - fc = getfirsttab(); - - if((fc > 0 && ev->x < TEXTW(before)) || ev->x < 0) - return; - - if(ev->y < 0 || ev-> y > bh) - return; - - for(i = (fc > 0) ? fc : 0; i < nclients; i++) { - if(clients[i]->tabx > ev->x) { - switch(ev->button) { - case Button1: - focus(i); - break; - case Button2: - focus(i); - killclient(NULL); - break; - case Button4: - case Button5: - arg.i = ev->button == Button4 ? -1 : 1; - rotate(&arg); - break; - } - break; - } - } -} - -void -cleanup(void) { - int i; - - for(i = 0; i < nclients; i++) { - focus(i); - killclient(NULL); - killclient(NULL); - XReparentWindow(dpy, clients[i]->win, root, 0, 0); - unmanage(i); - } - free(clients); - clients = NULL; - - 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); - free(cmd); -} - -void -clientmessage(const XEvent *e) { - const XClientMessageEvent *ev = &e->xclient; - - if(ev->message_type == wmatom[WMProtocols] - && ev->data.l[0] == wmatom[WMDelete]) { - running = False; - } -} - -void -configurenotify(const XEvent *e) { - const 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)); - if(sel > -1) - resize(sel, ww, wh - bh); - XSync(dpy, False); - } -} - -void -configurerequest(const XEvent *e) { - const XConfigureRequestEvent *ev = &e->xconfigurerequest; - XWindowChanges wc; - int c; - - if((c = getclient(ev->window)) > -1) { - wc.x = 0; - wc.y = bh; - wc.width = ww; - wc.height = wh - bh; - wc.border_width = 0; - wc.sibling = ev->above; - wc.stack_mode = ev->detail; - XConfigureWindow(dpy, clients[c]->win, ev->value_mask, &wc); - } -} - -void -createnotify(const XEvent *e) { - const XCreateWindowEvent *ev = &e->xcreatewindow; - - if(ev->window != win && getclient(ev->window) < 0) - manage(ev->window); -} - -void -destroynotify(const XEvent *e) { - const XDestroyWindowEvent *ev = &e->xdestroywindow; - int c; - - if((c = getclient(ev->window)) > -1) - unmanage(c); -} - -void -die(const char *errstr, ...) { - va_list ap; - - va_start(ap, errstr); - vfprintf(stderr, errstr, ap); - va_end(ap); - exit(EXIT_FAILURE); -} - -void -drawbar(void) { - unsigned long *col; - int c, fc, width, n = 0; - char *name = NULL; - - if(nclients == 0) { - dc.x = 0; - dc.w = ww; - XFetchName(dpy, win, &name); - drawtext(name ? name : "", dc.norm); - XCopyArea(dpy, dc.drawable, win, dc.gc, 0, 0, ww, bh, 0, 0); - XSync(dpy, False); - - return; - } - - width = ww; - clients[nclients-1]->tabx = -1; - fc = getfirsttab(); - if(fc > -1) - n = nclients - fc; - - if((n * tabwidth) > width) { - dc.w = TEXTW(after); - dc.x = width - dc.w; - drawtext(after, dc.sel); - width -= dc.w; - } - dc.x = 0; - - if(fc > 0) { - dc.w = TEXTW(before); - drawtext(before, dc.sel); - dc.x += dc.w; - width -= dc.w; - } - - for(c = (fc > 0)? fc : 0; c < nclients && dc.x < width; c++) { - dc.w = tabwidth; - if(c == sel) { - col = dc.sel; - if((n * tabwidth) > width) { - dc.w += width % tabwidth; - } else { - dc.w = width - (n - 1) * tabwidth; - } - } else { - col = dc.norm; - } - drawtext(clients[c]->name, col); - dc.x += dc.w; - clients[c]->tabx = dc.x; - } - XCopyArea(dpy, dc.drawable, win, dc.gc, 0, 0, ww, bh, 0, 0); - XSync(dpy, False); -} - -void -drawtext(const char *text, unsigned long col[ColLast]) { - int i, x, y, h, len, olen; - char buf[256]; - XRectangle r = { dc.x, dc.y, dc.w, dc.h }; - - XSetForeground(dpy, dc.gc, col[ColBG]); - 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; len--); - if(!len) - return; - - memcpy(buf, text, len); - 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, len); - } else { - XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); - } -} - -void * -emallocz(size_t size) { - void *p; - - if(!(p = calloc(1, size))) - die("tabbed: cannot malloc\n"); - return p; -} - -void * -erealloc(void *o, size_t size) { - void *p; - - if(!(p = realloc(o, size))) - die("tabbed: cannot realloc\n"); - return p; -} - -void -expose(const XEvent *e) { - const XExposeEvent *ev = &e->xexpose; - - if(ev->count == 0 && win == ev->window) - drawbar(); -} - -void -focus(int c) { - char buf[BUFSIZ] = "tabbed-"VERSION" ::"; - size_t i, n; - - /* If c, sel and clients are -1, raise tabbed-win itself */ - if(nclients == 0) { - cmd[cmd_append_pos] = NULL; - for(i = 0, n = strlen(buf); cmd[i] && n < sizeof(buf); i++) - n += snprintf(&buf[n], sizeof(buf) - n, " %s", cmd[i]); - - xsettitle(win, buf); - XRaiseWindow(dpy, win); - - return; - } - - if(c < 0 || c >= nclients) - return; - - resize(c, ww, wh - bh); - XRaiseWindow(dpy, clients[c]->win); - XSetInputFocus(dpy, clients[c]->win, RevertToParent, CurrentTime); - sendxembed(c, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0); - sendxembed(c, XEMBED_WINDOW_ACTIVATE, 0, 0, 0); - xsettitle(win, clients[c]->name); - - /* If sel is already c, change nothing. */ - if(sel != c) { - lastsel = sel; - sel = c; - } - - drawbar(); - XSync(dpy, False); -} - -void -focusin(const XEvent *e) { - const XFocusChangeEvent *ev = &e->xfocus; - int dummy; - Window focused; - - if(ev->mode != NotifyUngrab) { - XGetInputFocus(dpy, &focused, &dummy); - if(focused == win) - focus(sel); - } -} - -void -focusonce(const Arg *arg) { - nextfocus = True; -} - -void -fullscreen(const Arg *arg) { - XEvent e; - - e.type = ClientMessage; - e.xclient.window = win; - e.xclient.message_type = wmatom[WMState]; - e.xclient.format = 32; - e.xclient.data.l[0] = 2; - e.xclient.data.l[1] = wmatom[WMFullscreen]; - e.xclient.data.l[2] = 0; - XSendEvent(dpy, root, False, SubstructureNotifyMask, &e); -} - -char * -getatom(int a) { - static char buf[BUFSIZ]; - Atom adummy; - int idummy; - unsigned long ldummy; - unsigned char *p = NULL; - - XGetWindowProperty(dpy, win, wmatom[a], 0L, BUFSIZ, False, XA_STRING, - &adummy, &idummy, &ldummy, &ldummy, &p); - if(p) { - strncpy(buf, (char *)p, LENGTH(buf)-1); - } else { - buf[0] = '\0'; - } - XFree(p); - - return buf; -} - -int -getclient(Window w) { - int i; - - for(i = 0; i < nclients; i++) { - if(clients[i]->win == w) - return i; - } - - return -1; -} - -unsigned long -getcolor(const char *colstr) { - Colormap cmap = DefaultColormap(dpy, screen); - XColor color; - - if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) - die("tabbed: cannot allocate color '%s'\n", colstr); - - return color.pixel; -} - -int -getfirsttab(void) { - int c, n, fc; - - if(sel < 0) - return -1; - - c = sel; - fc = 0; - n = nclients; - if((n * tabwidth) > ww) { - for(; (c * tabwidth) > (ww / 2) - && (n * tabwidth) > ww; - c--, n--, fc++); - } - - return fc; -} - -Bool -gettextprop(Window w, Atom atom, char *text, unsigned int size) { - char **list = NULL; - int n; - XTextProperty name; - - if(!text || size == 0) - return False; - - text[0] = '\0'; - XGetTextProperty(dpy, w, &name, atom); - if(!name.nitems) - return False; - - if(name.encoding == XA_STRING) { - strncpy(text, (char *)name.value, size - 1); - } 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, **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", missing[n]); - XFreeStringList(missing); - } - - if(dc.font.set) { - 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++) { - 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("tabbed: 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; -} - -Bool -isprotodel(int c) { - int i, n; - Atom *protocols; - Bool ret = False; - - if(XGetWMProtocols(dpy, clients[c]->win, &protocols, &n)) { - for(i = 0; !ret && i < n; i++) { - if(protocols[i] == wmatom[WMDelete]) - ret = True; - } - XFree(protocols); - } - - return ret; -} - -void -keypress(const XEvent *e) { - const XKeyEvent *ev = &e->xkey; - unsigned int i; - KeySym keysym; - - keysym = XkbKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0, 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 -killclient(const Arg *arg) { - XEvent ev; - - if(sel < 0) - return; - - if(isprotodel(sel) && !clients[sel]->closed) { - ev.type = ClientMessage; - ev.xclient.window = clients[sel]->win; - ev.xclient.message_type = wmatom[WMProtocols]; - ev.xclient.format = 32; - ev.xclient.data.l[0] = wmatom[WMDelete]; - ev.xclient.data.l[1] = CurrentTime; - XSendEvent(dpy, clients[sel]->win, False, NoEventMask, &ev); - clients[sel]->closed = True; - } else { - XKillClient(dpy, clients[sel]->win); - } -} - -void -manage(Window w) { - updatenumlockmask(); - { - int i, j, nextpos; - unsigned int modifiers[] = { 0, LockMask, numlockmask, - numlockmask|LockMask }; - KeyCode code; - Client *c; - XEvent e; - - XWithdrawWindow(dpy, w, 0); - XReparentWindow(dpy, w, win, 0, bh); - XSelectInput(dpy, w, PropertyChangeMask - |StructureNotifyMask|EnterWindowMask); - XSync(dpy, False); - - for(i = 0; i < LENGTH(keys); i++) { - if((code = XKeysymToKeycode(dpy, keys[i].keysym))) { - for(j = 0; j < LENGTH(modifiers); j++) { - XGrabKey(dpy, code, keys[i].mod - | modifiers[j], w, - True, GrabModeAsync, - GrabModeAsync); - } - } - } - - c = emallocz(sizeof(*c)); - c->win = w; - - nclients++; - clients = erealloc(clients, sizeof(Client *) * nclients); - - if(npisrelative) { - nextpos = sel + newposition; - } else { - if(newposition < 0) { - nextpos = nclients - newposition; - } else { - nextpos = newposition; - } - } - if(nextpos >= nclients) - nextpos = nclients - 1; - if(nextpos < 0) - nextpos = 0; - - if(nclients > 1 && nextpos < nclients - 1) { - memmove(&clients[nextpos + 1], &clients[nextpos], - sizeof(Client *) * - (nclients - nextpos - 1)); - } - clients[nextpos] = c; - updatetitle(nextpos); - - XLowerWindow(dpy, w); - XMapWindow(dpy, w); - - e.xclient.window = w; - e.xclient.type = ClientMessage; - e.xclient.message_type = wmatom[XEmbed]; - e.xclient.format = 32; - e.xclient.data.l[0] = CurrentTime; - e.xclient.data.l[1] = XEMBED_EMBEDDED_NOTIFY; - e.xclient.data.l[2] = 0; - e.xclient.data.l[3] = win; - e.xclient.data.l[4] = 0; - XSendEvent(dpy, root, False, NoEventMask, &e); - - XSync(dpy, False); - - /* Adjust sel before focus does set it to lastsel. */ - if(sel >= nextpos) - sel++; - focus((nextfocus)? nextpos : ((sel < 0)? 0 : sel)); - nextfocus = foreground; - } -} - -void -maprequest(const XEvent *e) { - const XMapRequestEvent *ev = &e->xmaprequest; - - if(getclient(ev->window) < 0) - manage(ev->window); -} - -void -move(const Arg *arg) { - if(arg->i >= 0 && arg->i < nclients) - focus(arg->i); -} - -void -movetab(const Arg *arg) { - int c; - Client *new; - - if(sel < 0 || (arg->i == 0)) - return; - - c = sel + arg->i; - while(c >= nclients) - c -= nclients; - while(c < 0) - c += nclients; - - new = clients[c]; - clients[c] = clients[sel]; - clients[sel] = new; - - sel = c; - - drawbar(); -} - -void -propertynotify(const XEvent *e) { - const XPropertyEvent *ev = &e->xproperty; - int c; - char* selection = NULL; - Arg arg; - - if(ev->state == PropertyNewValue && ev->atom == wmatom[WMSelectTab]) { - selection = getatom(WMSelectTab); - if(!strncmp(selection, "0x", 2)) { - arg.i = getclient(strtoul(selection, NULL, 0)); - move(&arg); - } else { - cmd[cmd_append_pos] = selection; - arg.v = cmd; - spawn(&arg); - } - } else if(ev->state != PropertyDelete && ev->atom == XA_WM_NAME - && (c = getclient(ev->window)) > -1) { - updatetitle(c); - } -} - -void -resize(int c, int w, int h) { - XConfigureEvent ce; - XWindowChanges wc; - - ce.x = 0; - ce.y = bh; - ce.width = wc.width = w; - ce.height = wc.height = h; - ce.type = ConfigureNotify; - ce.display = dpy; - ce.event = clients[c]->win; - ce.window = clients[c]->win; - ce.above = None; - ce.override_redirect = False; - ce.border_width = 0; - - XConfigureWindow(dpy, clients[c]->win, CWWidth|CWHeight, &wc); - XSendEvent(dpy, clients[c]->win, False, StructureNotifyMask, - (XEvent *)&ce); -} - -void -rotate(const Arg *arg) { - int nsel = -1; - - if(sel < 0) - return; - - if(arg->i == 0) { - if(lastsel > -1) - focus(lastsel); - } else if(sel > -1) { - /* Rotating in an arg->i step around the clients. */ - nsel = sel + arg->i; - while(nsel >= nclients) - nsel -= nclients; - while(nsel < 0) - nsel += nclients; - focus(nsel); - } -} - -void -run(void) { - XEvent ev; - - /* main event loop */ - XSync(dpy, False); - drawbar(); - if(doinitspawn == True) - spawn(NULL); - - while(running) { - XNextEvent(dpy, &ev); - if(handler[ev.type]) - (handler[ev.type])(&ev); /* call handler */ - } -} - -void -sendxembed(int c, long msg, long detail, long d1, long d2) { - XEvent e = { 0 }; - - e.xclient.window = clients[c]->win; - e.xclient.type = ClientMessage; - e.xclient.message_type = wmatom[XEmbed]; - e.xclient.format = 32; - e.xclient.data.l[0] = CurrentTime; - e.xclient.data.l[1] = msg; - e.xclient.data.l[2] = detail; - e.xclient.data.l[3] = d1; - e.xclient.data.l[4] = d2; - XSendEvent(dpy, clients[c]->win, False, NoEventMask, &e); -} - -void -setcmd(int argc, char *argv[], int replace) { - int i; - - cmd = emallocz((argc+3) * sizeof(*cmd)); - if (argc == 0) - return; - for(i = 0; i < argc; i++) - cmd[i] = argv[i]; - cmd[(replace > 0)? replace : argc] = winid; - cmd_append_pos = argc + !replace; - cmd[cmd_append_pos] = cmd[cmd_append_pos+1] = NULL; -} - -void -setup(void) { - int bitm, tx, ty, tw, th, dh, dw, isfixed; - XClassHint class_hint; - XSizeHints *size_hint; - - /* clean up any zombies immediately */ - sigchld(0); - - /* init screen */ - screen = DefaultScreen(dpy); - root = RootWindow(dpy, screen); - initfont(font); - bh = dc.h = dc.font.height + 2; - - /* init atoms */ - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); - wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - wmatom[XEmbed] = XInternAtom(dpy, "_XEMBED", False); - wmatom[WMName] = XInternAtom(dpy, "_NET_WM_NAME", False); - wmatom[WMState] = XInternAtom(dpy, "_NET_WM_STATE", False); - wmatom[WMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); - wmatom[WMSelectTab] = XInternAtom(dpy, "_TABBED_SELECT_TAB", False); - - /* init appearance */ - wx = 0; - wy = 0; - ww = 800; - wh = 600; - isfixed = 0; - - if(geometry) { - tx = ty = tw = th = 0; - bitm = XParseGeometry(geometry, &tx, &ty, (unsigned *)&tw, - (unsigned *)&th); - if(bitm & XValue) - wx = tx; - if(bitm & YValue) - wy = ty; - if(bitm & WidthValue) - ww = tw; - if(bitm & HeightValue) - wh = th; - if(bitm & XNegative && wx == 0) - wx = -1; - if(bitm & YNegative && wy == 0) - wy = -1; - if(bitm & (HeightValue|WidthValue)) - isfixed = 1; - - dw = DisplayWidth(dpy, screen); - dh = DisplayHeight(dpy, screen); - if(wx < 0) - wx = dw + wx - ww - 1; - if(wy < 0) - wy = dh + wy - wh - 1; - } - - 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]); - XMapRaised(dpy, win); - XSelectInput(dpy, win, SubstructureNotifyMask|FocusChangeMask| - ButtonPressMask|ExposureMask|KeyPressMask|PropertyChangeMask| - StructureNotifyMask|SubstructureRedirectMask); - xerrorxlib = XSetErrorHandler(xerror); - - class_hint.res_name = wmname; - class_hint.res_class = "tabbed"; - XSetClassHint(dpy, win, &class_hint); - - size_hint = XAllocSizeHints(); - if(!isfixed) { - size_hint->flags = PSize; - size_hint->height = wh; - size_hint->width = ww; - } else { - size_hint->flags = PMaxSize | PMinSize; - size_hint->min_width = size_hint->max_width = ww; - size_hint->min_height = size_hint->max_height = wh; - } - XSetWMProperties(dpy, win, NULL, NULL, NULL, 0, size_hint, NULL, NULL); - XFree(size_hint); - - XSetWMProtocols(dpy, win, &wmatom[WMDelete], 1); - - snprintf(winid, sizeof(winid), "%lu", win); - setenv("XEMBED", winid, 1); - - nextfocus = foreground; - focus(-1); -} - -void -sigchld(int unused) { - if(signal(SIGCHLD, sigchld) == SIG_ERR) - die("tabbed: cannot install SIGCHLD handler"); - - while(0 < waitpid(-1, NULL, WNOHANG)); -} - -void -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); - fprintf(stderr, "tabbed: execvp %s", - ((char **)arg->v)[0]); - } else { - cmd[cmd_append_pos] = NULL; - execvp(cmd[0], cmd); - fprintf(stderr, "tabbed: execvp %s", cmd[0]); - } - perror(" failed"); - exit(0); - } -} - -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 -unmanage(int c) { - if(c < 0 || c >= nclients) { - drawbar(); - XSync(dpy, False); - return; - } - - if(!nclients) { - return; - } else if(c == 0) { - /* First client. */ - nclients--; - free(clients[0]); - memmove(&clients[0], &clients[1], sizeof(Client *) * nclients); - } else if(c == nclients - 1) { - /* Last client. */ - nclients--; - free(clients[c]); - clients = erealloc(clients, sizeof(Client *) * nclients); - } else { - /* Somewhere inbetween. */ - free(clients[c]); - memmove(&clients[c], &clients[c+1], - sizeof(Client *) * (nclients - (c + 1))); - nclients--; - } - - if(nclients <= 0) { - sel = -1; - lastsel = -1; - - if (closelastclient) { - running = False; - } else if (fillagain && running) { - spawn(NULL); - } - } else { - if(c == lastsel) { - lastsel = -1; - } else if(lastsel > c) { - lastsel--; - } - lastsel = MIN(lastsel, nclients - 1); - - if(c == sel) { - /* Note that focus() will never set lastsel == sel, - * so if here lastsel == sel, it was decreased by above if() clause - * and was actually (sel + 1) before. - */ - if(lastsel > 0) { - focus(lastsel); - } else { - focus(0); - lastsel = 1; - } - } else { - if(sel > c) - sel -= 1; - if(sel >= nclients) - sel = nclients - 1; - - focus(sel); - } - } - - drawbar(); - XSync(dpy, False); -} - -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); -} - -void -updatetitle(int c) { - if(!gettextprop(clients[c]->win, wmatom[WMName], - clients[c]->name, sizeof(clients[c]->name))) { - gettextprop(clients[c]->win, XA_WM_NAME, - clients[c]->name, sizeof(clients[c]->name)); - } - if(sel == c) - xsettitle(win, clients[c]->name); - drawbar(); -} - -/* There's no way to check accesses to destroyed windows, thus those cases are - * ignored (especially on UnmapNotify's). Other types of errors call Xlibs - * default error handler, which may call exit. */ -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 == 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 */ -} - -void -xsettitle(Window w, const char *str) { - XTextProperty xtp; - - if(XmbTextListToTextProperty(dpy, (char **)&str, 1, XCompoundTextStyle, - &xtp) == Success) { - XSetTextProperty(dpy, w, &xtp, wmatom[WMName]); - XSetTextProperty(dpy, w, &xtp, XA_WM_NAME); - XFree(xtp.value); - } -} - -char *argv0; - -void -usage(void) { - die("usage: %s [-dfhsv] [-g geometry] [-n name] [-p [s+/-]pos] [-r narg] " - "[-u color] [-U color] [-t color] [-T color] command...\n", argv0); -} - -int -main(int argc, char *argv[]) { - Bool detach = False; - int replace = 0; - char *pstr; - - ARGBEGIN { - case 'c': - closelastclient = True; - fillagain = False; - break; - case 'd': - detach = True; - break; - case 'f': - fillagain = True; - break; - case 'g': - geometry = EARGF(usage()); - break; - case 'n': - wmname = EARGF(usage()); - break; - case 'p': - pstr = EARGF(usage()); - if(pstr[0] == 's') { - npisrelative = True; - newposition = atoi(&pstr[1]); - } else { - newposition = atoi(pstr); - } - break; - case 'r': - replace = atoi(EARGF(usage())); - break; - case 's': - doinitspawn = False; - break; - case 'v': - die("tabbed-"VERSION", © 2009-2012" - " tabbed engineers, see LICENSE" - " for details.\n"); - break; - case 't': - selbgcolor = EARGF(usage()); - break; - case 'T': - selfgcolor = EARGF(usage()); - break; - case 'u': - normbgcolor = EARGF(usage()); - break; - case 'U': - normfgcolor = EARGF(usage()); - break; - default: - case 'h': - usage(); - } ARGEND; - - if(argc < 1) { - doinitspawn = False; - fillagain = False; - } - - setcmd(argc, argv, replace); - - if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) - 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); - - if(detach) { - if(fork() == 0) { - fclose(stdout); - } else { - if(dpy) - close(ConnectionNumber(dpy)); - return EXIT_SUCCESS; - } - } - - run(); - cleanup(); - XCloseDisplay(dpy); - - return EXIT_SUCCESS; -} - |