select or open new tab with Ctrl-T
The default config will display all open tabs in dmenu. You can either select one of them, or if you enter a string, that does not start with „0x“, tabbed will open a new tab and run the command specified at tabbed-startup but append the entered string to the command first. With tabbed -r 2 surf -e '' you can hit Ctrl-T and either select an already opened tab or enter an URL, which will be opened in a new tab with surf. Signed-off-by: Christoph Lohmann <20h@r-36.net>
This commit is contained in:
parent
b46a3a2788
commit
a1aa453e99
|
@ -19,11 +19,20 @@ static const Bool foreground = True;
|
|||
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 } },
|
||||
|
|
51
tabbed.c
51
tabbed.c
|
@ -48,7 +48,7 @@
|
|||
|
||||
enum { ColFG, ColBG, ColLast }; /* color */
|
||||
enum { WMProtocols, WMDelete, WMName, WMState, WMFullscreen,
|
||||
XEmbed, WMLast }; /* default atoms */
|
||||
XEmbed, WMSelectTab, WMLast }; /* default atoms */
|
||||
|
||||
typedef union {
|
||||
int i;
|
||||
|
@ -103,6 +103,7 @@ 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);
|
||||
|
@ -157,6 +158,7 @@ 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";
|
||||
|
@ -428,6 +430,7 @@ focus(int c) {
|
|||
|
||||
/* 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]);
|
||||
|
||||
|
@ -489,6 +492,26 @@ fullscreen(const Arg *arg) {
|
|||
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;
|
||||
|
@ -775,8 +798,20 @@ void
|
|||
propertynotify(const XEvent *e) {
|
||||
const XPropertyEvent *ev = &e->xproperty;
|
||||
int c;
|
||||
char* selection = NULL;
|
||||
Arg arg;
|
||||
|
||||
if(ev->state != PropertyDelete && ev->atom == XA_WM_NAME
|
||||
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);
|
||||
}
|
||||
|
@ -862,13 +897,14 @@ void
|
|||
setcmd(int argc, char *argv[], int replace) {
|
||||
int i;
|
||||
|
||||
cmd = emallocz((argc+2) * sizeof(*cmd));
|
||||
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[argc + !(replace > 0)] = NULL;
|
||||
cmd_append_pos = argc + !replace;
|
||||
cmd[cmd_append_pos] = cmd[cmd_append_pos+1] = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -892,8 +928,8 @@ setup(void) {
|
|||
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[WMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
|
||||
wmatom[WMSelectTab] = XInternAtom(dpy, "_TABBED_SELECT_TAB", False);
|
||||
|
||||
/* init appearance */
|
||||
wx = 0;
|
||||
|
@ -943,7 +979,7 @@ setup(void) {
|
|||
dc.norm[ColFG], dc.norm[ColBG]);
|
||||
XMapRaised(dpy, win);
|
||||
XSelectInput(dpy, win, SubstructureNotifyMask|FocusChangeMask|
|
||||
ButtonPressMask|ExposureMask|KeyPressMask|
|
||||
ButtonPressMask|ExposureMask|KeyPressMask|PropertyChangeMask|
|
||||
StructureNotifyMask|SubstructureRedirectMask);
|
||||
xerrorxlib = XSetErrorHandler(xerror);
|
||||
|
||||
|
@ -993,6 +1029,7 @@ spawn(const Arg *arg) {
|
|||
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]);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue