=== added file 'switchto.c' --- switchto.c 1970-01-01 00:00:00 +0000 +++ switchto.c 2007-05-08 21:11:04 +0000 @@ -0,0 +1,106 @@ +/* Author: Riccardo Murri + * See LICENSE file for license details. */ +#include "dwm.h" +#include +#include +#include +#include + + +static Bool +matches(Client *c, regex_t *re) +{ + XClassHint ch = { 0 }; + unsigned int len; + char *s; + Bool result; + + XGetClassHint(dpy, c->win, &ch); + len = (4 + (ch.res_class? strlen(ch.res_class) : 0) + + (ch.res_name? strlen(ch.res_name) : 0) + + strlen(c->name)); + s = emallocz(len); + snprintf(s, len, "%s:%s:%s", + ch.res_class ? ch.res_class : "", + ch.res_name ? ch.res_name : "", + c->name); + result = (REG_NOMATCH != regexec(re, s, 1, NULL, 0)); + free(s); + return result; +} + + +/** Focus client matching given rule, and optionally raise or zoom it. + +Scan list of clients (but the currently-focused one) and focus the +first one that matches the given rule. If no client, matches the +rule, spawn a new one. + +@param rule A string in the form "Class:instance:title-regex:command", + just like +@param do_raise If True, map and raise client window. +@param do_zoom If True, call dwm "zoom" after focusing client. +*/ +static void +_switchto (const char *arg, Bool do_raise, Bool do_zoom) +{ + char *cmd, *rule; + unsigned int colons; + Client *match = NULL; + regex_t re; + + /* advance until right after third occurrence of ':' in `rule` */ + for (cmd = rule, colons=0; colons<3 && *cmd!='\0'; cmd++) + if (':' == *cmd) + colons++; + + /* copy rule part */ + rule = emallocz(cmd - arg); + strncpy(rule, arg, cmd-arg-1); + + /* compile rule to regex */ + if(regcomp(&re, rule, REG_EXTENDED|REG_NOSUB)) + return; + + if(clients) { + Client *c, *last; + /* find last client in list */ + for(c = clients; c; c = c->next) + last = c; + + /* find matching window searching from end of list backwards, + or we'll just switch between the first two matching clients */ + for(c = last; c && !match; c = c->prev) { + if (sel != c && matches(c, &re)) + match = c; + } + } + if(NULL == match && sel && matches(sel, &re)) + return; /* currently-selected window is the only match */ + + if(match) { + focus(match); + if(do_raise) + XMapRaised(dpy, match->win); + else + XMapWindow(dpy, match->win); + if (do_zoom) + zoom(NULL); + } + else { + spawn (cmd); + /* FIXME: should take extra steps to focus/zoom this one? */ + } +} + +void +focusnamed(const char* rule) +{ + _switchto(rule, True, False); +} + +void +zoomnamed(const char* rule) +{ + _switchto(rule, True, True); +} === modified file 'Makefile' --- Makefile 2007-05-04 21:02:42 +0000 +++ Makefile 2007-05-08 21:11:27 +0000 @@ -3,7 +3,7 @@ include config.mk -SRC = client.c draw.c event.c layout.c main.c tag.c util.c +SRC = client.c draw.c event.c layout.c main.c switchto.c tag.c util.c OBJ = ${SRC:.c=.o} all: options dwm === modified file 'config.default.h' --- config.default.h 2007-05-04 21:02:42 +0000 +++ config.default.h 2007-05-08 21:13:26 +0000 @@ -44,6 +44,7 @@ /* modifier key function argument */ \ { MODKEY|ShiftMask, XK_Return, spawn, "exec xterm" }, \ { MODKEY, XK_p, spawn, "exe=`dmenu_path | dmenu` && exec $exe" }, \ + { MODKEY|ControlMask|ShiftMask, XK_Return, zoomnamed, "URxvt:xterm:.*:urxvtc" }, \ { MODKEY, XK_space, setlayout, NULL }, \ { MODKEY, XK_h, incmasterw, "-32" }, \ { MODKEY, XK_l, incmasterw, "32" }, \ === modified file 'dwm.h' --- dwm.h 2007-05-04 21:02:42 +0000 +++ dwm.h 2007-05-08 21:10:31 +0000 @@ -133,6 +133,13 @@ void quit(const char *arg); /* quit dwm nicely */ int xerror(Display *dsply, XErrorEvent *ee); /* dwm's X error handler */ +/* switchto.c */ + +void focusnamed(const char* arg); /* focus+raise window identified by class:instance:title regex, + or spawn a new instance if none is found. */ +void zoomnamed(const char* arg); /* zoom window identified by class:instance:title regex, + or spawn a new instance if none is found. */ + /* tag.c */ void compileregs(void); /* initialize regexps of rules defined in config.h */ Bool isvisible(Client *c); /* returns True if client is visible */