commit 68b77ab4e8e55214a4e71626e94e0a126fe23d41
parent ec18eb22e960272a122c8427540fc123af110619
Author: Kris Maglione <kris@suckless.org>
Date: Fri, 25 Jun 2010 17:21:12 -0400
Change format of bar files. Refactor fs.c. Add M-n/M-b to rc scripts. Add showkeys to plan9port rc. Update docs. Linkify code fragments in wmii.tex.
Diffstat:
13 files changed, 511 insertions(+), 422 deletions(-)
diff --git a/alternative_wmiircs/plan9port/wmiirc b/alternative_wmiircs/plan9port/wmiirc
@@ -61,8 +61,8 @@ wmiir write /rules <<!
# Status Bar Info
fn status {
- echo -n `{uptime | sed 's/.*://; s/,//g'} '|' \
- `{date} }
+ echo -n label `{uptime | sed 's/.*://; s/,//g'} '|' \
+ `{date} }
# Generic overridable startup details
fn startup { witray & }
@@ -86,19 +86,19 @@ fn sigexit {
wi_cleankeys}
fn Event-CreateTag {
- echo $wmiinormcol $* | wmiir create /lbar/$"*}
+ echo colors $wmiinormcol $wi_newline label $* | wmiir create /lbar/$"*}
fn Event-DestroyTag {
wmiir remove /lbar/$"*}
fn Event-FocusTag {
- wmiir xwrite /lbar/$"* $wmiifocuscol $*}
+ wmiir xwrite /lbar/$"* colors $wmiifocuscol}
fn Event-UnfocusTag {
- wmiir xwrite /lbar/$"* $wmiinormcol $*}
+ wmiir xwrite /lbar/$"* colors $wmiinormcol}
fn Event-UrgentTag {
shift
- wmiir xwrite /lbar/$"* '*'$"*}
+ wmiir xwrite /lbar/$"* label '*'$"*}
fn Event-NotUrgentTag {
shift
- wmiir xwrite /lbar/$"* $"*}
+ wmiir xwrite /lbar/$"* label $"*}
fn Event-AreaFocus {
if(~ $1 '~')
setbackground $wmiifloatbackground
@@ -116,7 +116,7 @@ fn Event-Unresponsive {
wmiir xwrite /client/$client/ctl slay
}&}
fn Event-Notice {
- wmiir xwrite $noticebar $wi_arg
+ wmiir xwrite $noticebar label $wi_arg
/bin/kill $xpid >[2]/dev/null # Let's hope this isn't reused...
{ sleep $noticetimeout; wmiir xwrite $noticebar ' ' }& # Bug...
@@ -152,21 +152,24 @@ fn Event-LeftBarMouseDown {
wi_fnmenu LBar $* &}
# Actions
+fn Action-exec {
+ wmiir xwrite /ctl exec $*}
+fn Action-quit {
+ wmiir xwrite /ctl quit}
fn Action-rehash {
comm -23 <{ls `{namespace}^/proglist.* >[2]/dev/null | awk -F'.' '{print $NF}'} \
<{ps | awk '{print $2}'} |
while(id=`{read})
rm `{namespace}^/proglist.$id
wi_proglist $PATH >$progs_file}
-fn Action-quit {
- wmiir xwrite /ctl quit}
-fn Action-exec {
- wmiir xwrite /ctl exec $*}
+fn Action-showkeys {
+ echo $wmiikeyhelp | xmessage -file -
+}
fn Action-status {
flag x -; flag r -
if(wmiir remove /rbar/status >[2]/dev/null)
sleep 2
- echo $wmiinormcol | wmiir create /rbar/status
+ echo colors $wmiinormcol | wmiir create /rbar/status
while(status | wmiir write /rbar/status)
sleep 1
}
@@ -181,84 +184,103 @@ startup
# Key Bindings
_keys = `{wi_getfuns Key}
+fn keygroup {
+ wmiikeyhelp = $wmiikeyhelp ^ $wi_newline ^ ' ' ^ $"* ^ $wi_newline}
fn key {
+ help=$1; shift
key=()
- for(k) if(! ~ $k $_keys) key = ($key Key-$k)
+ for(k) {
+ if(! ~ $k $_keys) {
+ ifs=() { wmiikeyhelp = `{awk 'BEGIN {
+ printf "%s %- 20s %s\n", ENVIRON["wmiikeyhelp"], ENVIRON["k"], ENVIRON["help"]
+ exit }'} }
+ key = ($key Key-$k)}}
~ $#key 0}
-# This is... ugly.
-
-key $MODKEY-Control-t || fn $key {
- switch(`{wmiir read /keys | wc -l}) {
- case 0 1
- wmiir xwrite /keys $keys
- wmiir xwrite /ctl grabmod $MODKEY
- case *
- ifs=() { keys=`{wmiir read /keys} }
- wmiir xwrite /keys $MODKEY-Control-t
- wmiir xwrite /ctl grabmod Mod3
- }}
-
-key $MODKEY-$LEFT || fn $key {
+keygroup Moving around
+key 'Select the client to the left' $MODKEY-$LEFT || fn $key {
wmiir xwrite /tag/sel/ctl select left}
-key $MODKEY-$RIGHT || fn $key {
+key 'Select the client to the right' $MODKEY-$RIGHT || fn $key {
wmiir xwrite /tag/sel/ctl select right}
-key $MODKEY-$DOWN || fn $key {
+key 'Select the client below' $MODKEY-$DOWN || fn $key {
wmiir xwrite /tag/sel/ctl select down}
-key $MODKEY-$UP || fn $key {
+key 'Select the client above' $MODKEY-$UP || fn $key {
wmiir xwrite /tag/sel/ctl select up}
-key $MODKEY-Control-$DOWN || fn $key {
+
+key 'Toggle between floating and managed layers' $MODKEY-space || fn $key {
+ wmiir xwrite /tag/sel/ctl select toggle}
+
+keygroup Moving through stacks
+key 'Select the stack below' $MODKEY-Control-$DOWN || fn $key {
wmiir xwrite /tag/sel/ctl select down stack}
-key $MODKEY-Control-$UP || fn $key {
+key 'Select the stack above' $MODKEY-Control-$UP || fn $key {
wmiir xwrite /tag/sel/ctl select up stack}
-key $MODKEY-Shift-$LEFT || fn $key {
+keygroup Moving clients around
+key 'Move selected client to the left' $MODKEY-Shift-$LEFT || fn $key {
wmiir xwrite /tag/sel/ctl send sel left}
-key $MODKEY-Shift-$RIGHT || fn $key {
+key 'Move selected client to the right' $MODKEY-Shift-$RIGHT || fn $key {
wmiir xwrite /tag/sel/ctl send sel right}
-key $MODKEY-Shift-$DOWN || fn $key {
+key 'Move selected client down' $MODKEY-Shift-$DOWN || fn $key {
wmiir xwrite /tag/sel/ctl send sel down}
-key $MODKEY-Shift-$UP || fn $key {
+key 'Move selected client up' $MODKEY-Shift-$UP || fn $key {
wmiir xwrite /tag/sel/ctl send sel up}
-key $MODKEY-f || fn $key {
+key 'Toggle selected client between floating and managed layers' $MODKEY-Shift-space || fn $key {
+ wmiir xwrite /tag/sel/ctl send sel toggle}
+
+keygroup Client actions
+key 'Toggle selected client''s fullsceen state' $MODKEY-f || fn $key {
wmiir xwrite /client/sel/ctl Fullscreen toggle}
+key 'Close client' $MODKEY-Shift-c || fn $key {
+ wmiir xwrite /client/sel/ctl kill}
-key $MODKEY-space || fn $key {
- wmiir xwrite /tag/sel/ctl select toggle}
-key $MODKEY-Shift-space || fn $key {
- wmiir xwrite /tag/sel/ctl send sel toggle}
-key $MODKEY-d || fn $key {
+keygroup Changing column modes
+key 'Set column to default mode' $MODKEY-d || fn $key {
wmiir xwrite /tag/sel/ctl colmode sel default-max}
-key $MODKEY-s || fn $key {
+key 'Toggle between floating and managed layers' $MODKEY-s || fn $key {
wmiir xwrite /tag/sel/ctl colmode sel stack-max}
-key $MODKEY-m || fn $key {
+key 'Set column to max mode' $MODKEY-m || fn $key {
wmiir xwrite /tag/sel/ctl colmode sel stack+max}
-key $MODKEY-Shift-c || fn $key {
- wmiir xwrite /client/sel/ctl kill}
-
-key $MODKEY-a || fn $key {
+keygroup Running programs
+key 'Open wmii actions menu' $MODKEY-a || fn $key {
Action `{wi_actions | wimenu -h $hist.action -n $histlen} &}
-key $MODKEY-p || fn $key {
+key 'Open program menu' $MODKEY-p || fn $key {
ifs=() { cmd = `{wimenu -h $hist.prog -n $histlen <$progs_file} }
wi_runcmd $cmd & }
-key $MODKEY-Return || fn $key {
+key 'Launch a terminal' $MODKEY-Return || fn $key {
wi_runcmd $WMII_TERM &}
-key $MODKEY-t || fn $key {
+keygroup Other
+key 'Toggle all other key bindings' $MODKEY-Control-t || fn $key {
+ switch(`{wmiir read /keys | wc -l}) {
+ case 0 1
+ wmiir xwrite /keys $keys
+ wmiir xwrite /ctl grabmod $MODKEY
+ case *
+ ifs=() { keys=`{wmiir read /keys} }
+ wmiir xwrite /keys $MODKEY-Control-t
+ wmiir xwrite /ctl grabmod Mod3
+ }}
+
+keygroup Tag actions
+key 'Change to another tag' $MODKEY-t || fn $key {
tag=`{wi_tags | wimenu -h $hist.tag -n 50} && wmiir xwrite /ctl view $tag &}
-key $MODKEY-Shift-t || fn $key {
+key 'Retag the selected client' $MODKEY-Shift-t || fn $key {
sel=`{wi_selclient} {
tag=`{wi_tags | wimenu -h $hist.tag -n 50} && wmiir xwrite /client/$sel/tags $tag } &}
+key 'Move to the next tag' $MODKEY-n || fn $key {
+ wmiir xwrite /ctl view `{wi_tags | wi_nexttag}}
+key 'Move to the previous tag' $MODKEY-b || fn $key {
+ wmiir xwrite /ctl view `{wi_tags | sort -r | wi_nexttag}}
-key $MODKEY-^`{seq 0 9} || fn $key {
+key 'Move to the numbered view' $MODKEY-^`{seq 0 9} || fn $key {
wmiir xwrite /ctl view `{echo $1 | sed 's/.*-//'}}
-key Shift-$MODKEY-^`{seq 0 9} || fn $key {
+key 'Retag selected client with the numbered tag' Shift-$MODKEY-^`{seq 0 9} || fn $key {
wmiir xwrite /client/sel/tags `{echo $1 | sed 's/.*-//'}}
-
-#` WM Configuration
+# WM Configuration
wmiir write /ctl <<!
grabmod $MODKEY
border 2
@@ -286,10 +308,8 @@ ifs=$wi_newline {
seltag=`{wi_seltag}
for(tag in `{wi_tags}) {{
if(~ $tag $seltag)
- echo $wmiifocuscol $tag
+ echo colors $wmiifocuscol $wi_newline label $tag
if not
- echo $wmiinormcol $tag
+ echo colors $wmiinormcol $wi_newline label $tag
} | wmiir create /lbar/$tag}}
-
wi_eventloop
-
diff --git a/alternative_wmiircs/python/pygmi/fs.py b/alternative_wmiircs/python/pygmi/fs.py
@@ -452,82 +452,6 @@ class Tag(Dir):
frame = self.framespec(frame)
self['grow'] = '%s %s %s' % (frame, dir, str(amount or ''))
-class Button(object):
- sides = {
- 'left': 'lbar',
- 'right': 'rbar',
- }
- def __init__(self, side, name, colors=None, label=None):
- self.side = side
- self.name = name
- self.base_path = self.sides[side]
- self.path = '%s/%s' % (self.base_path, self.name)
- self.file = None
- self._colors = wmii.cache['normcolors']
- self._label = ''
- if colors or label:
- self.create(colors, label)
-
- def create(self, colors=None, label=None):
- def fail(resp, exc, tb):
- self.file = None
- if not self.file:
- self.file = client.create(self.path, ORDWR)
- if colors or label:
- self.file.awrite(self.getval(colors, label), offset=0, fail=fail)
-
- def remove(self):
- if self.file:
- self.file.aremove()
- self.file = None
-
- def getval(self, colors=None, label=None):
- if label is not None:
- self._label = label
- if colors is not None:
- self._colors = colors
- return ' '.join([Color(c).hex for c in self._colors or self.colors] + [unicode(self._label or '')])
-
- colors = property(
- lambda self: self.file and Colors(self.file.read(offset=0).split(' ')[:3]) or (),
- lambda self, val: self.create(colors=val))
-
- label = property(
- lambda self: self.file and self.file.read(offset=0).split(' ', 3)[3] or '',
- lambda self, val: self.create(label=val))
-
- @classmethod
- def all(cls, side):
- return (Button(side, s.name)
- for s in client.readdir(cls.sides[side])
- if s.name != 'sel')
-
-class Colors(utf8):
- def __init__(self, foreground=None, background=None, border=None):
- vals = foreground, background, border
- self.vals = tuple(map(Color, vals))
-
- def __iter__(self):
- return iter(self.vals)
- def __list__(self):
- return list(self.vals)
- def __tuple__(self):
- return self.vals
-
- @classmethod
- def from_string(cls, val):
- return cls(*val.split(' '))
-
- def __getitem__(self, key):
- if isinstance(key, basestring):
- key = {'foreground': 0, 'background': 1, 'border': 2}[key]
- return self.vals[key]
-
- def __unicode__(self):
- return ' '.join(c.hex for c in self.vals)
- def __repr__(self):
- return 'Colors(%s, %s, %s)' % tuple(repr(c.rgb) for c in self.vals)
-
class Color(utf8):
def __init__(self, colors):
if isinstance(colors, Color):
@@ -563,6 +487,73 @@ class Color(utf8):
def __repr__(self):
return 'Color(%s)' % repr(self.rgb)
+class Colors(utf8):
+ def __init__(self, foreground=None, background=None, border=None):
+ vals = foreground, background, border
+ self.vals = tuple(map(Color, vals))
+
+ def __iter__(self):
+ return iter(self.vals)
+ def __list__(self):
+ return list(self.vals)
+ def __tuple__(self):
+ return self.vals
+
+ @classmethod
+ def from_string(cls, val):
+ return cls(*val.split(' '))
+
+ def __getitem__(self, key):
+ if isinstance(key, basestring):
+ key = {'foreground': 0, 'background': 1, 'border': 2}[key]
+ return self.vals[key]
+
+ def __unicode__(self):
+ return ' '.join(c.hex for c in self.vals)
+ def __repr__(self):
+ return 'Colors(%s, %s, %s)' % tuple(repr(c.rgb) for c in self.vals)
+
+class Button(Ctl):
+ sides = {
+ 'left': 'lbar',
+ 'right': 'rbar',
+ }
+ ctl_types = {
+ 'colors': (Colors.from_string, lambda c: str(Colors(*c))),
+ }
+ colors = Dir.ctl_property('colors')
+ label = Dir.ctl_property('label')
+
+ def __init__(self, side, name, colors=None, label=None):
+ super(Button, self).__init__()
+ self.side = side
+ self.name = name
+ self.base_path = self.sides[side]
+ self.ctl_path = '%s/%s' % (self.base_path, self.name)
+ self.file = None
+ self.create(colors, label)
+
+ def create(self, colors=None, label=None):
+ def fail(resp, exc, tb):
+ self.file = None
+ if not self.file:
+ self.file = client.create(self.ctl_path, ORDWR)
+ if colors:
+ self.colors = colors
+ if label:
+ self.label = label
+
+ def remove(self):
+ if self.file:
+ self.file.aremove()
+ self.file = None
+
+ @classmethod
+ def all(cls, side):
+ return (Button(side, s.name)
+ for s in client.readdir(cls.sides[side])
+ if s.name != 'sel')
+
class Rules(collections.MutableMapping, utf8):
_items = ()
diff --git a/cmd/wmii.rc.rc b/cmd/wmii.rc.rc
@@ -9,6 +9,7 @@
wmiiscript=$1
wmiikeys=()
+wmiikeyhelp=''
wi_newline='
'
@@ -134,15 +135,21 @@ fn wi_selclient {
wmiir read /client/sel/ctl | sed 1q
}
-fn wi_readevent {
- wmiir read /event
+fn wi_nexttag {
+ awk -v 'curtag='^`{wi_seltag} '
+ NR==1 {first = $0}
+ $0==curtag { if(getline) print $0; else print first; exit }'
}
fn wi_eventloop {
wi_initkeys
- wi_readevent |
- while(ifs=$wi_ewlinel{wi_event=`{read}}) {
+ {
+ if(~ $1 -i)
+ cat
+ if not
+ wmiir read /event
+ } | while(ifs=$wi_newline{wi_event=`{read}}) {
ifs=$wi_newline{
wi_arg=`{echo $wi_event | sed 's/^[^ ]+ //'}}
* = `{echo $wi_event}
diff --git a/cmd/wmii.sh.sh b/cmd/wmii.sh.sh
@@ -86,10 +86,6 @@ _wi_script() {
_wi_text() {
cat <<'!'
-Event Start
- if [ "$1" = "$wmiiscript" ]; then
- exit
- fi
Event Key
Key "$@"
!
@@ -188,6 +184,12 @@ wi_selclient() {
wmiir read /client/sel/ctl | sed 1q | tr -d '\012'
}
+wi_nexttag() {
+ awk -v curtag=$(wi_seltag) '
+ NR==1 {first = $0}
+ $0==curtag { if(getline) print $0; else print first; exit }'
+}
+
wi_eventloop() {
echo "$Keys" | wmiir write /keys
@@ -201,6 +203,8 @@ wi_eventloop() {
unset IFS
set -- $wi_event
event=$1; shift
+ [ "$event" = Start -a "$1" = "$wmiiscript" ] &&
+ exit
( Event $event "$@" )
done
true
diff --git a/cmd/wmii/bar.c b/cmd/wmii/bar.c
@@ -194,34 +194,6 @@ bar_draw(WMScreen *s) {
copyimage(s->barwin, r, disp.ibuf, ZP);
}
-void
-bar_load(Bar *b) {
- IxpMsg m;
- char *p, *q;
-
- p = b->buf;
- m = ixp_message(p, strlen(p), 0);
-
- if(!waserror()) { /* Ignore errors. */
- msg_parsecolors(&m, &b->col);
- poperror();
- }
-
- q = (char*)m.end-1;
- while(q >= (char*)m.pos && *q == '\n')
- *q-- = '\0';
-
- q = b->text;
- utflcpy(q, (char*)m.pos, sizeof b->text);
-
- p[0] = '\0';
- strlcat(p, b->col.colstr, sizeof b->buf);
- strlcat(p, " ", sizeof b->buf);
- strlcat(p, b->text, sizeof b->buf);
-
- bar_draw(b->screen);
-}
-
Bar*
bar_find(Bar *bp, const char *name) {
Bar *b;
diff --git a/cmd/wmii/dat.h b/cmd/wmii/dat.h
@@ -303,7 +303,8 @@ struct View {
#endif
/* global variables */
-EXTERN struct {
+typedef struct Defs Defs;
+EXTERN struct Defs {
CTuple focuscolor;
CTuple normcolor;
Font* font;
diff --git a/cmd/wmii/fns.h b/cmd/wmii/fns.h
@@ -69,7 +69,6 @@ void bar_destroy(Bar**, Bar*);
void bar_draw(WMScreen*);
Bar* bar_find(Bar*, const char*);
void bar_init(WMScreen*);
-void bar_load(Bar*);
void bar_resize(WMScreen*);
void bar_sety(WMScreen*, int);
void bar_setbounds(WMScreen*, int, int);
@@ -210,6 +209,7 @@ void spawn_command(const char*);
/* message.c */
char* mask(char**, int*, int*);
+char* message_bar(Bar*, IxpMsg*);
char* message_client(Client*, IxpMsg*);
char* message_root(void*, IxpMsg*);
char* message_view(View*, IxpMsg*);
@@ -219,6 +219,7 @@ char* msg_getword(IxpMsg*, char*);
void msg_parsecolors(IxpMsg*, CTuple*);
char* msg_selectarea(Area*, IxpMsg*);
char* msg_sendclient(View*, IxpMsg*, bool swap);
+char* readctl_bar(Bar*);
char* readctl_client(Client*);
char* readctl_root(void);
char* readctl_view(View*);
diff --git a/cmd/wmii/fs.c b/cmd/wmii/fs.c
@@ -123,6 +123,28 @@ static IxpDirtab* dirtab[] = {
[FsDTag] = dirtab_tag,
};
typedef char* (*MsgFunc)(void*, IxpMsg*);
+typedef char* (*BufFunc)(void*);
+
+typedef struct ActionTab ActionTab;
+static struct ActionTab {
+ MsgFunc msg;
+ BufFunc read;
+ size_t buffer;
+ size_t size;
+ int max;
+} actiontab[] = {
+ [FsFBar] = { .msg = (MsgFunc)message_bar, .read = (BufFunc)readctl_bar },
+ [FsFCctl] = { .msg = (MsgFunc)message_client, .read = (BufFunc)readctl_client },
+ [FsFRctl] = { .msg = (MsgFunc)message_root, .read = (BufFunc)readctl_root },
+ [FsFTctl] = { .msg = (MsgFunc)message_view, .read = (BufFunc)readctl_view },
+ [FsFTindex] = { .msg = (MsgFunc)0, .read = (BufFunc)view_index },
+ [FsFColRules] = { .buffer = offsetof(Ruleset, string), .size = offsetof(Ruleset, size) },
+ [FsFKeys] = { .buffer = offsetof(Defs, keys), .size = offsetof(Defs, keyssz) },
+ [FsFRules] = { .buffer = offsetof(Ruleset, string), .size = offsetof(Ruleset, size) },
+ [FsFClabel] = { .buffer = offsetof(Client, name), .max = sizeof ((Client*)0)->name },
+ [FsFCtags] = { .buffer = offsetof(Client, tags), .max = sizeof ((Client*)0)->tags },
+ [FsFprops] = { .buffer = offsetof(Client, props), .max = sizeof ((Client*)0)->props },
+};
void
event(const char *format, ...) {
@@ -335,6 +357,9 @@ lookup_file(IxpFileId *parent, char *name)
case FsFColRules:
file->p.rule = &def.colrules;
break;
+ case FsFKeys:
+ file->p.ref = &def;
+ break;
case FsFRules:
file->p.rule = &def.rules;
break;
@@ -374,21 +399,19 @@ fs_walk(Ixp9Req *r) {
static uint
fs_size(IxpFileId *f) {
- switch(f->tab.type) {
- default:
- return 0;
- case FsFColRules:
- case FsFRules:
- return f->p.rule->size;
- case FsFKeys:
- return def.keyssz;
- case FsFCtags:
- return strlen(f->p.client->tags);
- case FsFClabel:
- return strlen(f->p.client->name);
- case FsFprops:
- return strlen(f->p.client->props);
- }
+ ActionTab *t;
+
+ t = &actiontab[f->tab.type];
+ if(f->tab.type < nelem(actiontab))
+ if(t->size)
+ return structmember(f->p.ref, int, t->size);
+ else if(t->buffer && t->max)
+ return strlen(structptr(f->p.ref, char, t->buffer));
+ else if(t->buffer)
+ return strlen(structmember(f->p.ref, char*, t->buffer));
+ else if(t->read)
+ return strlen(t->read(f->p.ref));
+ return 0;
}
void
@@ -422,9 +445,11 @@ void
fs_read(Ixp9Req *r) {
char *buf;
IxpFileId *f;
- int n;
+ ActionTab *t;
+ int n, found;
f = r->fid->aux;
+ found = 0;
if(!ixp_srv_verifyfile(f, lookup_file)) {
ixp_respond(r, Enofile);
@@ -440,53 +465,26 @@ fs_read(Ixp9Req *r) {
ixp_pending_respond(r);
return;
}
- switch(f->tab.type) {
- case FsFprops:
- ixp_srv_readbuf(r, f->p.client->props, strlen(f->p.client->props));
- ixp_respond(r, nil);
- return;
- case FsFColRules:
- case FsFRules:
- ixp_srv_readbuf(r, f->p.rule->string, f->p.rule->size);
- ixp_respond(r, nil);
- return;
- case FsFKeys:
- ixp_srv_readbuf(r, def.keys, def.keyssz);
- ixp_respond(r, nil);
- return;
- case FsFCtags:
- ixp_srv_readbuf(r, f->p.client->tags, strlen(f->p.client->tags));
- ixp_respond(r, nil);
- return;
- case FsFClabel:
- ixp_srv_readbuf(r, f->p.client->name, strlen(f->p.client->name));
- ixp_respond(r, nil);
- return;
- case FsFBar:
- ixp_srv_readbuf(r, f->p.bar->buf, strlen(f->p.bar->buf));
- ixp_respond(r, nil);
- return;
- case FsFRctl:
- buf = readctl_root();
- ixp_srv_readbuf(r, buf, strlen(buf));
- ixp_respond(r, nil);
- return;
- case FsFCctl:
- buf = readctl_client(f->p.client);
- ixp_srv_readbuf(r, buf, strlen(buf));
- ixp_respond(r, nil);
- return;
- case FsFTindex:
- buf = view_index(f->p.view);
- ixp_srv_readbuf(r, buf, strlen(buf));
- ixp_respond(r, nil);
- return;
- case FsFTctl:
- buf = readctl_view(f->p.view);
- n = strlen(buf);
+ t = &actiontab[f->tab.type];
+ if(f->tab.type < nelem(actiontab)) {
+ if(t->read)
+ buf = t->read(f->p.ref);
+ else if(t->buffer && t->max)
+ buf = structptr(f->p.ref, char, t->buffer);
+ else if(t->buffer)
+ buf = structmember(f->p.ref, char*, t->buffer);
+ else
+ goto done;
+ n = t->size ? structmember(f->p.ref, int, t->size) : strlen(buf);
ixp_srv_readbuf(r, buf, n);
ixp_respond(r, nil);
- return;
+ found++;
+ }
+ done:
+ switch(f->tab.type) {
+ default:
+ if(found)
+ return;
}
}
/* This should not be called if the file is not open for reading. */
@@ -495,12 +493,13 @@ fs_read(Ixp9Req *r) {
void
fs_write(Ixp9Req *r) {
- MsgFunc mf;
IxpFileId *f;
+ ActionTab *t;
char *errstr;
- char *p;
- uint i;
+ int found;
+ found = 0;
+ errstr = nil;
if(r->ifcall.io.count == 0) {
ixp_respond(r, nil);
return;
@@ -517,25 +516,30 @@ fs_write(Ixp9Req *r) {
return;
}
- switch(f->tab.type) {
- case FsFColRules:
- case FsFRules:
- ixp_srv_writebuf(r, &f->p.rule->string, &f->p.rule->size, 0);
- ixp_respond(r, nil);
- break;
- case FsFKeys:
- ixp_srv_writebuf(r, &def.keys, &def.keyssz, 0);
+ t = &actiontab[f->tab.type];
+ if(f->tab.type < nelem(actiontab)) {
+ if(t->msg) {
+ errstr = ixp_srv_writectl(r, t->msg);
+ r->ofcall.io.count = r->ifcall.io.count;
+ }
+ else if(t->buffer && t->max)
+ ixp_srv_writebuf(r, (char*[]){ structptr(f->p.ref, char, t->buffer) },
+ t->size ? structptr(f->p.ref, uint, t->size) : nil,
+ t->max);
+ else if(t->buffer)
+ ixp_srv_writebuf(r, structptr(f->p.ref, char*, t->buffer),
+ t->size ? structptr(f->p.ref, uint, t->size) : nil,
+ t->max);
+ else
+ goto done;
ixp_respond(r, nil);
- break;
+ found++;
+ }
+done:
+ switch(f->tab.type) {
case FsFClabel:
- ixp_srv_data2cstring(r);
- utfecpy(f->p.client->name,
- f->p.client->name + sizeof client->name,
- r->ifcall.io.data);
frame_draw(f->p.client->sel);
update_class(f->p.client);
- r->ofcall.io.count = r->ifcall.io.count;
- ixp_respond(r, nil);
break;
case FsFCtags:
ixp_srv_data2cstring(r);
@@ -543,28 +547,6 @@ fs_write(Ixp9Req *r) {
r->ofcall.io.count = r->ifcall.io.count;
ixp_respond(r, nil);
break;
- case FsFBar:
- i = strlen(f->p.bar->buf);
- p = f->p.bar->buf;
- ixp_srv_writebuf(r, &p, &i, 279);
- bar_load(f->p.bar);
- r->ofcall.io.count = i - r->ifcall.io.offset;
- ixp_respond(r, nil);
- break;
- case FsFCctl:
- mf = (MsgFunc)message_client;
- goto msg;
- case FsFTctl:
- mf = (MsgFunc)message_view;
- goto msg;
- case FsFRctl:
- mf = (MsgFunc)message_root;
- goto msg;
- msg:
- errstr = ixp_srv_writectl(r, mf);
- r->ofcall.io.count = r->ifcall.io.count;
- ixp_respond(r, errstr);
- break;
case FsFEvent:
if(r->ifcall.io.data[r->ifcall.io.count-1] == '\n')
event("%.*s", (int)r->ifcall.io.count, r->ifcall.io.data);
@@ -575,7 +557,8 @@ fs_write(Ixp9Req *r) {
break;
default:
/* This should not be called if the file is not open for writing. */
- die("Write called on an unwritable file");
+ if(!found)
+ die("Write called on an unwritable file");
}
poperror();
return;
@@ -652,7 +635,6 @@ fs_remove(Ixp9Req *r) {
return;
}
-
switch(f->tab.type) {
default:
ixp_respond(r, Enoperm);
@@ -661,9 +643,12 @@ fs_remove(Ixp9Req *r) {
s = f->p.bar->screen;
bar_destroy(f->next->p.bar_p, f->p.bar);
bar_draw(s);
- ixp_respond(r, nil);
+ break;
+ case FsDClient:
+ client_kill(f->p.client, true);
break;
}
+ ixp_respond(r, nil);
}
void
diff --git a/cmd/wmii/message.c b/cmd/wmii/message.c
@@ -29,6 +29,7 @@ enum {
LBORDER,
LCLIENT,
LCOLMODE,
+ LCOLORS,
LDEBUG,
LDOWN,
LEXEC,
@@ -42,6 +43,7 @@ enum {
LGROW,
LINCMODE,
LKILL,
+ LLABEL,
LLEFT,
LNORMCOLORS,
LNUDGE,
@@ -68,6 +70,7 @@ char *symtab[] = {
"border",
"client",
"colmode",
+ "colors",
"debug",
"down",
"exec",
@@ -81,6 +84,7 @@ char *symtab[] = {
"grow",
"incmode",
"kill",
+ "label",
"left",
"normcolors",
"nudge",
@@ -472,6 +476,31 @@ getframe(View *v, int scrn, IxpMsg *m) {
}
char*
+readctl_bar(Bar *b) {
+ bufclear();
+ bufprint("colors %s\n", b->col.colstr);
+ bufprint("label %s\n", b->text);
+ return buffer;
+}
+
+char*
+message_bar(Bar *b, IxpMsg *m) {
+
+ switch(getsym(msg_getword(m, nil))) {
+ case LCOLORS:
+ msg_parsecolors(m, &b->col);
+ break;
+ case LLABEL:
+ utflcpy(b->text, (char*)m->pos, sizeof b->text);
+ break;
+ default:
+ error(Ebadvalue);
+ }
+ bar_draw(b->screen);
+ return nil;
+}
+
+char*
readctl_client(Client *c) {
bufclear();
bufprint("%#C\n", c);
diff --git a/doc/wmii.tex b/doc/wmii.tex
@@ -13,7 +13,12 @@
\usepackage{xcolor}
\usepackage[xetex,breaklinks,colorlinks,linkcolor=black]{hyperref}
-% Indexes
+\let\EA=\expandafter
+
+\newif\ifexpandfragments
+\newif\ifdefinefragments
+
+%% Indexes
\makeindex
\let\primary=\textbf
@@ -26,36 +31,63 @@
\def\man#1#2{#2\textbf{(#1)}}
-% Key specs
+\makeatletter
+
+%% Key specs
\def\key#1{{\small$\langle$\addfontfeature{Numbers=Lining}#1\/$\rangle$}}
\let\<=<
\catcode`\<=\active
\def<#1>{\key{#1}}
-% Display ‹...› and «...» as text in left and right pointing
-% angle brackets. I use «» and ‹› because my terminal doesn't
-% display left and right pointing angle brackets properly, and
-% Xorg's compose maps don't provide them, anyway.
+%% Display ‹...› and «...» as text in left and right pointing
+%% angle brackets. I use «» and ‹› because my terminal doesn't
+%% display left and right pointing angle brackets properly, and
+%% Xorg's compose maps don't provide them, anyway.
+\def\«{«}\def\‹{‹}
\catcode`\«=\active
\catcode`\‹=\active
\def‹#1›{$\langle${\itshape#1}$\rangle$}
\def«#1»{$\langle\langle${\itshape#1}$\rangle\rangle$}
+\catcode`\∅=\active
+\def∅{\box0}
+\def«{%
+ \let\dofragment@target=\hyperlink%
+ \@ifnextchar*\dofragment@@\dofragment@}
+\def\dofragment@@*{%
+ \let\dofragment@target=\hypertarget%
+ \dofragment@}
+\def\dofragment@#1»{%
+ \setbox0=\hbox{$\langle\langle${\itshape#1}$\rangle\rangle$}%
+ \ifexpandfragments%
+ \def\a{\sp\sp\comment \boxzero^^J}%
+ \begingroup%
+ \def\ { }\xdef\@frag@name{#1}%
+ \endgroup%
+ \UseFragment{∅}\@frag@name%
+ \else%
+ \dofragment@target{frag:#1}{\box0}%
+ \fi}
+
% Display |...| as verbatim, teletype text.
\DefineShortVerb{\|}
-\makeatletter
\let\idx@@heading\chapter
-\let\:=:
-\catcode`\:=\active
-\def:{\@ifnextchar:{\coloncoloneq}{\:}}
-\def\coloncoloneq#1{\@ifnextchar={$\Coloneqq$\coloncoloneqq}{\:\:}}
-\def\coloncoloneqq#1{}
-
-% Create a verbatim {code} environment which highlights strings
-% and comments. Several unicode characters are hacked to replace
-% the grabbed characters, since we can't escape them in the
-% verbatim environment.
+\def\:{:}
+\iffalse
+ \catcode`\:=\active
+ \gdef:{\@ifnextchar:{\coloncoloneq}{\:}}
+ \gdef\coloncoloneq#1{\@ifnextchar={$\Coloneqq$\coloncoloneqq}{\:\:}}
+ \gdef\coloncoloneqq#1{}
+\fi
+\def\≔{≔}
+\catcode`\≔=\active
+\def≔{\ensuremath{\Coloneqq}}
+
+%% Create a verbatim {code} environment which highlights strings
+%% and comments. Several unicode characters are hacked to replace
+%% the grabbed characters, since we can't escape them in the
+%% verbatim environment.
\colorlet{comment}{gray}
\colorlet{string}{red!100!black!90}
\let\‘=‘
@@ -67,17 +99,66 @@
\catcode`‘=\active
\def“¶1”{{\color{string}\“¶1”}}%
\def‘¶1’{{\color{string}\‘¶1’}}%
+\def\comment{\itshape\color{comment}\let“=\“\let‘=\‘\#}
+\def\docodes{\catcode`\#=\active\catcode`“=\active\catcode`‘=\active\catcode`\☺=0}
+\def\dodefineactive{
+ \let#=\comment
+ }
\DefineVerbatimEnvironment{code}{Verbatim}{xleftmargin=2em,gobble=2,%
- codes={\catcode`\#=\active\catcode`\:=\active\catcode`“=\active\catcode`‘=\active},%
- defineactive={%
- \def#{\itshape\color{comment}\let“=\“\let‘=\‘\#}%
- }}
+ codes={\docodes},%
+ defineactive={\dodefineactive}}
\catcode`\#=6
\catcode`“=12
\catcode`‘=12
-% Convenience defs for the various wmii commands, and a few
-% others.
+%% Save code fragments for piecing together later
+\begingroup
+ \catcode`\@=0
+ @catcode`\\=12
+ @gdef@bcode{@detokenize{\begin{code}^^J}}
+ @gdef@ecode{@detokenize{\end{code}^^J}}
+ @catcode`@ =12@gdef@sp{ }
+@endgroup
+
+% Ripped from fancyverb
+% I'm currently rather unfond of it.
+\def\Fragment{\FV@Environment{}{Fragment}}
+\def\FVB@Fragment#1{%
+ \@bsphack
+ \begingroup
+ \FV@UseKeyValues
+ \gdef\Fragment@Name{#1}%
+ \xdef\Fragment@Prefix{\«*#1» \≔^^J}
+ \xdef\TheFragment{}
+ \def\FV@ProcessLine##1{%
+ \edef\frag{\detokenize{##1^^J}}%
+ \xdef\TheFragment{\TheFragment\frag}}%
+ \FV@Scan}
+\def\FVE@Fragment{%
+ \EA\global\EA\let
+ \csname SV@\Fragment@Name\endcsname\TheFragment%
+ \endgroup%
+ \EA\UseFragment\EA{\Fragment@Prefix}\Fragment@Name}
+\DefineVerbatimEnvironment{Fragment}{Fragment}{}
+
+\def\UseFragment#1#2{
+ \begingroup
+ % \message{UseFragment #2^^J}
+ \EA\let\EA\a\csname SV@#2\endcsname
+ \ifx\a\undefined\def\a{\ldots}\fi
+ \ifx\FV@EnvironName\relax%
+ \edef\a{\bcode\detokenize{++#1}\a\ecode}\else%
+ \edef\a{\detokenize{#1}\a}\fi%
+ \newtoks\tokens
+ \EA\tokens\EA{\a}
+ \everyeof{\noexpand}%
+ % \EA\message\EA{\the\tokens}
+ \scantokens\EA{\the\tokens}
+ \endgroup
+}
+
+%% Convenience defs for the various wmii commands, and a few
+%% others.
\def\wmii{\texttt{wmii}}
\def\wiIXmenu{\texttt{wi9menu}}
\def\wimenu{\texttt{wimenu}}
@@ -125,7 +206,6 @@ This file is distributed under the same terms as wmii:
\parindent=0pt
\parskip=1em
-\catcode`\:=12
Copyright © 2009 Kris Maglione <\href{mailto:maglione.k@gmail.com}{maglione.k@gmail.com}>
Permission is hereby granted, free of charge, to any person obtaining a
@@ -635,8 +715,7 @@ windows, and changes of focus and views.
We'll start building our configuration with an event processing
framework:
-\begin{code}
- «Event Loop» ::=
+\begin{Fragment}{Event Loop}
# Broadcast a custom event
wmiir xwrite /event Start wmiirc
@@ -657,13 +736,12 @@ framework:
«Event Handlers»
esac
done
-\end{code}
+\end{Fragment}
Now, we need to consider which types of events we'll need to
handle:
-\begin{code}
- «Event Handlers» ::=
+\begin{Fragment}{Event Handlers}
«View Button Events»
«Urgency Events»
«Unresponsive Clients»
@@ -671,37 +749,45 @@ handle:
«Key Events»
«Client Menu Events»
«Tag Menu Events»
-\end{code}
+\end{Fragment}
\section{Bar Items}
The bar is described by the files in the two directories |/lbar/| and
|/rbar/| for buttons on the left and right side of the bar,
-respectively. The format of the files is:
+respectively. The files act as control files (section
+\ref{sec:controlfiles}) with the contents:
\begin{code}
- ‹Color Tuple› ‹Label›
+ color ‹Color Tuple›
+ label ‹Label›
\end{code}
-although the color tuple may be elided in cases where the label
-doesn't match its format.
-
A ‹Color Tuple› is defined as:
\begin{code}
- ‹tuple› ::= ‹foreground color› ‹background color› ‹border color›
- ‹color› ::= #‹6 character RGB hex color code›
+ ‹Color Tuple› ≔ ‹foreground color› ‹background color› ‹border color›
+ ‹* Color› ≔ ‹RGB color› | ‹RGBA color›
+ ‹RGB color› ≔ #‹6 character RGB hex color code›
+ ‹RGBA color› ≔ rgba:‹red›/‹green›/‹blue›/‹alpha›
\end{code}
+\noindent
+where all of the colors are represented as lowercase,
+hexidecimal values. In the case of RGBA colors, they may be 1--4
+characters long, though they will be standardized internally to
+2 characters.
+
+\medskip
+
Let's define our basic theme information now:
-\begin{code}
- «Theme Definitions» ::=
+\begin{Fragment}{Theme Definitions}
normcolors=‘#000000 #c1c48b #81654f’
focuscolors=‘#000000 #81654f #000000’
background=‘#333333’
font=‘drift,-*-fixed-*-*-*-*-9-*-*-*-*-*-*-*’
-\end{code}
+\end{Fragment}
\subsection{View Buttons}
@@ -712,8 +798,7 @@ our view event handlers:
\index{events!DestroyTag}
\index{events!FocusTag}
\index{events!UnfocusTag}
-\begin{code}
- «View Button Events» ::=
+\begin{Fragment}{View Button Events}
CreateTag) # CreateTag ‹Tag Name›
echo $normcolors $1 | wmiir create /lbar/$1;;
DestroyTag) # DestroyTag ‹Tag Name›
@@ -722,7 +807,7 @@ our view event handlers:
wmiir xwrite /lbar/$1 $focuscolors $1;;
UnfocusTag) # UnfocusTag ‹Tag Name›
wmiir xwrite /lbar/$1 $normcolors $1;;
-\end{code}
+\end{Fragment}
\subsection{Urgency}
@@ -732,13 +817,12 @@ Windows can specify that they require attention, and in X11
parlance, this is called urgency. When a window requests
attention as such, or declares that it's been satisfied, \wmii\
broadcasts an event for the client and an event for each view
-that it belongs to, and fills in the client's layout box. It's
-the job of a script to decide how to handle it above and beyond
-that. The standard scripts simply mark urgent views with an
-asterisk:
+that it belongs to. It also fills in the layout box of any
+client deemed urgent. It's the job of a script to decide how to
+handle urgency events above and beyond that basic measure. The
+standard scripts simply mark urgent views with an asterisk:
-\begin{code}
- «Urgency Events» ::=
+\begin{Fragment}{Urgency Events}
# The urgency events are ‘Client’ events when the program
# owning the window sets its urgency state. They're ‘Manager’
# events when wmii or the wmii user sets the state.
@@ -746,7 +830,7 @@ asterisk:
wmiir xwrite /lbar/$2 $2;;
NotUrgentTag) # NotUrgentTag ‹‘Client’ or ‘Manager’› ‹Tag Name›
wmiir xwrite /lbar/$2 $2;;
-\end{code}
+\end{Fragment}
\index{events!UrgentTag|)}
\index{events!NotUrgentTag|)}
@@ -756,18 +840,17 @@ The standard scripts provide a custom Notice event for
displaying status information. The events appear in the long bar
between the left and right sides for five seconds.
-\begin{code}
- «Notice Events» ::=
+\begin{Fragment}{Notice Events}
Notice)
wmiir xwrite /rbar/!notice $line
kill $xpid 2>/dev/null # Let's hope this isn't reused...
{ sleep 5; wmiir xwrite /rbar/!notice ‘ ’; } &
xpid = $!;;
-\end{code}
+\end{Fragment}
\section{Keys}
-\label{keybindings}
+\label{sec:keybindings}
\index{key bindings}
\index{filesystem!/!keys}
\index{filesystem!/!event}
@@ -798,8 +881,7 @@ Examples of key bindings:
Now, let's bind the keys we plan on using:
-\begin{code}
- «Bind Keys» ::=
+\begin{Fragment}{Bind Keys}
{
cat <<!
Mod4-space
@@ -828,12 +910,11 @@ Now, let's bind the keys we plan on using:
echo Mod4-Shift-$i
done
} | wmiir write /keys
-\end{code}
+\end{Fragment}
and lay a framework for processing their events:
-\begin{code}
- «Key Events» ::=
+\begin{Fragment}{Key Events}
Key) # Key ‹Key Name›
case $1 in
«Motion Keys»
@@ -844,7 +925,7 @@ and lay a framework for processing their events:
«Tag Selection Keys»
«Tagging Keys»
esac;;
-\end{code}
+\end{Fragment}
\section{Click Menus}
@@ -853,15 +934,16 @@ reach for the keyboard. To help cope, \wmii\ provides a
mouse-driven, single-click menu. The default configuration uses
it for client and tag menus.
-\begin{code}
- «Click Menu Initialization» ::=
+\begin{Fragment}{Click Menu Initialization}
clickmenu() {
if res=$(wmii9menu -- “$@”); then eval “$res”; fi
}
-\end{code}
+\end{Fragment}
\section{Control Files}
+\label{sec:controlfiles}
+
Several directories including the root, have control files,
named |ctl|. These files are used to control the object (e.g., a
client or tag) represented by the directory. Each line of the
@@ -937,7 +1019,10 @@ client. The files in these directories are:
\item[pid] Read-only value of the PID of the program that
owns the window, if the value is available and the
process is on the same machine as wmii.
- \item[slay] When written, the client is killed peremptorily.
+ \item[slay] When written, the client is disconnected
+ peremptorily. If the client's PID is available and the
+ process is the same machine as wmii, its parent process
+ is killed
\item[tags] The client's tags. The same as the tags file.
\item[urgent] The client's urgency state. When |on|, the
client's layout box will be highlighted. Possible values
@@ -953,19 +1038,21 @@ client. The files in these directories are:
\item[tags]
\index{filesystem!/client/*/@\clientlabel!tags}
The client's tags. Tag names are separated by |+|, |-|, or
- |^| signs. Tags beginning and ending with |/| are treated as
- regular expressions, which place the client on any extant
- matching tag\footnote{While a client with a regex tag will
- always appear in all matching views, it will not keep those
- views in existence. When the last client explicitly tagged
- with a view is removed, the view is deleted as soon as it
- becomes inactive.}. If the written value begins with a |+|,
- |-|, or |^|, the tags are updated rather than overwritten.
- Tag names which directly follow a |-| sign are removed
- rather than added, while those following a |^| are toggled.
- Regular expression tags which directly follow a minus sign
- are treated as exclusion expressions. For example, the tag
- string |+/foo/-/food/| will match the tag
+ |^| signs. Tag names which directly follow a |+| sign are
+ added, while whose following a |-| sign are removed and
+ those following a |^| are toggled. If the value written
+ begins with one of these characters, the value is appended
+ to the clients tags rather than replacing them.
+
+ Tags formatted as |/‹regex›/| are treated as regular
+ expressions, which place the client on any extant matching
+ tag\footnote{While a client with a regex tag will always
+ appear in all matching views, it will not keep those views
+ in existence. When the last client explicitly tagged with a
+ view is removed, the view is deleted as soon as it becomes
+ inactive.}. Regular expression tags which directly follow a
+ minus sign are treated as exclusion expressions. For
+ example, the tag string |+/foo/-/food/| will match the tag
|foobar|, but not the tag |foodstand|.
\end{description}
@@ -975,16 +1062,14 @@ client. The files in these directories are:
To control clients, we'll add the following key bindings:
-\begin{code}
- «Client Command Keys» ::=
+\begin{Fragment}{Client Command Keys}
Mod4-Shift-c) wmiir xwrite /client/sel/ctl kill;;
Mod4-f) wmiir xwrite /client/sel/ctl Fullscreen toggle;;
-\end{code}
+\end{Fragment}
And to manage their tags, we'll need:
-\begin{code}
- «Tagging Keys» ::=
+\begin{Fragment}{Tagging Keys}
Mod4-Shift-t)
# Get the selected client's id
c=$(wmiir read /client/sel/ctl | sed 1q)
@@ -994,19 +1079,18 @@ And to manage their tags, we'll need:
wmiir xwrite /client/$c/tags $tag;;
Mod4-Shift-[0-9])
wmiir xwrite /client/sel/tags ${1##*-};;
-\end{code}
+\end{Fragment}
\subsection{Click Menus}
\index{events!ClientMouseDown}
-\begin{code}
- «Client Menu Events» ::=
+\begin{Fragment}{Client Menu Events}
ClientMouseDown) # ClientMouseDown ‹Client ID› ‹Button›
[ $2 = 3 ] && clickmenu \
“Delete:wmiir xwrite /client/$1/ctl kill” \
“Kill: wmiirxwrite /client/$1/ctl slay” \
“Fullscreen:wmiir xwrite /client/$1/ctl fullscreen on”
-\end{code}
+\end{Fragment}
\subsection{Unresponsive Clients}
@@ -1015,8 +1099,7 @@ When \wmii\ tries to close a window, it waits 8 seconds for the
client to respond, and then lets its scripts decide what to do
with it. The stock scripts prompt the user for input:
-\begin{code}
- «Unresponsive Clients» ::=
+\begin{Fragment}{Unresponsive Clients}
UnresponsiveClient) # UnresponsiveClient ‹Client ID›
{
# Use wihack to make the xmessage a transient window of
@@ -1029,7 +1112,7 @@ with it. The stock scripts prompt the user for input:
$(wmiir read /client/$1/label))
[ $resp = Kill ] && wmiir xwrite /client/$1/ctl slay
} &;;
-\end{code}
+\end{Fragment}
\index{events!UnresponsiveClient|)}
\section{Views}
@@ -1117,36 +1200,36 @@ in these directories are:
We'll use the following key bindings to interact with views:
-\begin{code}
- «Motion Keys» ::=
+\begin{Fragment}{Motion Keys}
Mod4-h) wmiir xwrite /tag/sel/ctl select left;;
Mod4-l) wmiir xwrite /tag/sel/ctl select right;;
Mod4-k) wmiir xwrite /tag/sel/ctl select up;;
Mod4-j) wmiir xwrite /tag/sel/ctl select down;;
Mod4-space) wmiir xwrite /tag/sel/ctl select toggle;;
+\end{Fragment}
- «Client Movement Keys» ::=
+\begin{Fragment}{Client Movement Keys}
Mod4-Shift-h) wmiir xwrite /tag/sel/ctl send sel left;;
Mod4-Shift-l) wmiir xwrite /tag/sel/ctl send sel right;;
Mod4-Shift-k) wmiir xwrite /tag/sel/ctl send sel up;;
Mod4-Shift-j) wmiir xwrite /tag/sel/ctl send sel down;;
Mod4-Shift-space) wmiir xwrite /tag/sel/ctl send sel toggle;;
+\end{Fragment}
- «Column Mode Keys» ::=
+\begin{Fragment}{Column Mode Keys}
Mod4-d) wmiir xwrite /tag/sel/ctl colmode sel -stack-max;;
Mod4-s) wmiir xwrite /tag/sel/ctl colmode sel stack-max;;
Mod4-m) wmiir xwrite /tag/sel/ctl colmode sel stack+max;;
-\end{code}
+\end{Fragment}
\subsection{Click Menus}
\index{events!LeftBarMouseDown}
-\begin{code}
- «Tag Menu Events» ::=
+\begin{Fragment}{Tag Menu Events}
LeftBarMouseDown) # LeftBarMouseDown ‹Button› ‹Bar Name›
[ $1 = 3 ] && clickmenu \
“Delete:delete_view $2”
-\end{code}
+\end{Fragment}
\section{Command and Program Execution}
@@ -1160,28 +1243,26 @@ commands.
We use |wmiir setsid| to launch programs with their own session
IDs to prevent untoward effects when this script dies.
-\begin{code}
- «Command Execution Initialization» ::=
+\begin{Fragment}{Command Execution Initialization}
terminal() { wmiir setsid xterm “$@” }
proglist() {
IFS=:
wmiir proglist $1 | sort | uniq
unset IFS
}
-\end{code}
+\end{Fragment}
\subsection{Key Bindings}
-\begin{code}
- «Command Execution Keys» ::=
+\begin{Fragment}{Command Execution Keys}
Mod4-Return) terminal & ;;
- Mod4-p) eval exec wmiir setsid "$(proglist $PATH | wimenu)" &;;
+ Mod4-p) eval exec wmiir setsid “$(proglist $PATH | wimenu)” &;;
Mod4-a) {
set -- $(proglist $WMII_CONFPATH | wimenu)
which=$(which which)
prog=$(PATH=$WMII_CONFPATH $which $1); shift
eval exec $prog “$@”
} &;;
-\end{code}
+\end{Fragment}
\section{The Root}
@@ -1243,9 +1324,9 @@ The root filesystem contains the following:
searched for the executable. Otherwise, the whole
argument is passed to the shell for evaluation.
\end{description}
- \item[keys] The global keybindings. See section \ref{keybindings}.
+ \item[keys] The global keybindings. See section \ref{sec:keybindings}.
\index{filesystem!/!keys|primary}
- \item[event] The global event feed. See section \ref{keybindings}.
+ \item[event] The global event feed. See section \ref{sec:keybindings}.
\index{filesystem!/!event|primary}
\item[colrules]
\index{filesystem!/!colrules}
@@ -1260,7 +1341,7 @@ The root filesystem contains the following:
Where,
\begin{code}
- ‹width› := ‹percent of screen› | ‹pixels›px
+ ‹width› ≔ ‹percent of screen› | ‹pixels›px
\end{code}
When a new column, ‹n›, is created on a view whose name
@@ -1306,8 +1387,7 @@ The root filesystem contains the following:
We'll need to let \wmii\ know about our previously defined theme
information:
-\begin{code}
- «Configuration» ::=
+\begin{Fragment}{Configuration}
«Theme Definitions»
xsetroot -solid $background
@@ -1318,14 +1398,13 @@ information:
font $font
grabmod Mod4
!
-\end{code}
+\end{Fragment}
\subsection{Key Bindings}
And we need a few more key bindings to select our views:
-\begin{code}
- «Tag Selection Keys» ::=
+\begin{Fragment}{Tag Selection Keys}
Mod4-t)
# Prompt the user for a tag
tags=$(wmiir ls /tag | sed ‘s,/,,; /^sel$/d’ | wimenu)
@@ -1333,7 +1412,7 @@ And we need a few more key bindings to select our views:
wmiir xwrite /ctl view $tags;;
Mod4-[0-9])
wmiir xwrite /ctl view ${1##*-};;
-\end{code}
+\end{Fragment}
\section{Tieing it All Together}
@@ -1501,7 +1580,7 @@ For clarity, here is the end result:
# «Command Execution Keys»
Mod4-Return) terminal & ;;
- Mod4-p) eval exec wmiir setsid "$(proglist $PATH | wimenu)" &;;
+ Mod4-p) eval exec wmiir setsid “$(proglist $PATH | wimenu)” &;;
Mod4-a) {
set -- $(proglist $WMII_CONFPATH | wimenu)
prog=$(PATH=$WMII_CONFPATH which $1); shift
diff --git a/include/stuff/base.h b/include/stuff/base.h
@@ -17,8 +17,10 @@
#ifndef offsetof
# define offsetof(type, member) ((size_t)&((type*)0)->member)
#endif
+#define structptr(ptr, type, offset) \
+ ((type*)((char*)(ptr) + (offset)))
#define structmember(ptr, type, offset) \
- (*(type*)((char*)(ptr) + (offset)))
+ (*structptr(ptr, type, offset))
#undef uchar
#undef ushort
diff --git a/man/wmii.man1 b/man/wmii.man1
@@ -157,6 +157,8 @@ key binding quick-reference.
| Mod-k | Move to a window _above_ the one currently focused
| Mod-space | Toggle between the managed and floating layers
| Mod-t <tag> | Move to the view of the given <tag>
+| Mod-n | Move to the next view
+| Mod-b | Move to the previous view
| Mod-//[0-9]// | Move to the view with the given number
=== Moving Things Around ===
@@ -473,12 +475,9 @@ under '/rbar/' appear on the right, with the leftmost item
occupying all extra available space. The items are sorted
lexicographically.
-The files may be read to obtain the colors and text of the bars.
-The colors are at the beginning of the string, represented as a
-tuple of 3 hex color codes for the foreground, background, and
-border, respectively. When writing the bar files, the colors may
-be omitted if the text would not otherwise appear to contain
-them.
+The files may be read or written to obtain or alter the colors
+and text of the bars. The format is similar to the various _ctl_
+files and should be self explanitory.
= FILES =
diff --git a/rc/wmiirc.sh b/rc/wmiirc.sh
@@ -65,7 +65,7 @@ wmiir write /rules <<!
# Status Bar Info
status() {
- echo -n $(uptime | sed 's/.*://; s/,//g') '|' $(date)
+ echo -n label $(uptime | sed 's/.*://; s/,//g') '|' $(date)
}
# Generic overridable startup details
@@ -75,26 +75,26 @@ local_events() { true;}
wi_runconf -s wmiirc_local
startup
-echo $WMII_NORMCOLORS | wmiir create $noticebar
+echo colors $WMII_NORMCOLORS | wmiir create $noticebar
# Event processing
events() {
cat <<'!'
# Events
Event CreateTag
- echo "$WMII_NORMCOLORS" "$@" | wmiir create "/lbar/$@"
+ echo colors "$WMII_NORMCOLORS$wi_newline" label "$@" | wmiir create "/lbar/$@"
Event DestroyTag
wmiir remove "/lbar/$@"
Event FocusTag
- wmiir xwrite "/lbar/$@" "$WMII_FOCUSCOLORS" "$@"
+ wmiir xwrite "/lbar/$@" colors "$WMII_FOCUSCOLORS"
Event UnfocusTag
- wmiir xwrite "/lbar/$@" "$WMII_NORMCOLORS" "$@"
+ wmiir xwrite "/lbar/$@" colors "$WMII_NORMCOLORS"
Event UrgentTag
shift
- wmiir xwrite "/lbar/$@" "*$@"
+ wmiir xwrite "/lbar/$@" label "*$@"
Event NotUrgentTag
shift
- wmiir xwrite "/lbar/$@" "$@"
+ wmiir xwrite "/lbar/$@" label "$@"
Event LeftBarClick LeftBarDND
shift
wmiir xwrite /ctl view "$@"
@@ -129,19 +129,12 @@ Event ClientMouseDown
Menu LBar-3-Delete
tag=$1; clients=$(wmiir read "/tag/$tag/index" | awk '/[^#]/{print $2}')
for c in $clients; do
- if [ "$tag" = "$(wmiir read /client/$c/tags)" ]; then
- wmiir xwrite /client/$c/ctl kill
- else
- wmiir xwrite /client/$c/tags -$tag
- fi
- if [ "$tag" = "$(wi_seltag)" ]; then
- newtag=$(wi_tags | awk -v't='$tag '
- $1 == t { if(!l) getline l
- print l
- exit }
- { l = $0 }')
- wmiir xwrite /ctl view $newtag
+ if [ "$tag" = "$(wmiir read /client/$c/tags)" ]
+ then wmiir xwrite /client/$c/ctl kill
+ else wmiir xwrite /client/$c/tags -$tag
fi
+ [ "$tag" = "$(wi_seltag)" ] &&
+ wmiir xwrite /ctl view $(wi_tags | wi_nexttag)
done
Event LeftBarMouseDown
wi_fnmenu LBar "$@" &
@@ -160,7 +153,7 @@ Action status
if wmiir remove /rbar/status 2>/dev/null; then
sleep 2
fi
- echo "$WMII_NORMCOLORS" | wmiir create /rbar/status
+ echo colors "$WMII_NORMCOLORS" | wmiir create /rbar/status
while status | wmiir write /rbar/status; do
sleep 1
done
@@ -238,6 +231,10 @@ Key $MODKEY-t # Change to another tag
Key $MODKEY-Shift-t # Retag the selected client
# Assumes left-to-right order of evaluation
wmiir xwrite /client/$(wi_selclient)/tags $(wi_tags | wimenu -h "${hist}.tags" -n 50) &
+Key $MODKEY-n # Move to the next tag
+ wmiir xwrite /ctl view $(wi_tags | wi_nexttag)
+Key $MODKEY-b # Move to the previous tag
+ wmiir xwrite /ctl view $(wi_tags | sort -r | wi_nexttag)
!
for i in 0 1 2 3 4 5 6 7 8 9; do
cat <<!
@@ -273,9 +270,11 @@ unset IFS
wi_tags | while read tag
do
if [ "$tag" = "$seltag" ]; then
- echo "$WMII_FOCUSCOLORS" "$tag"
+ echo colors "$WMII_FOCUSCOLORS"
+ echo label $tag
else
- echo "$WMII_NORMCOLORS" "$tag"
+ echo colors "$WMII_NORMCOLORS"
+ echo label $tag
fi | wmiir create "/lbar/$tag"
done