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.

This commit is contained in:
Kris Maglione 2010-06-25 17:21:12 -04:00
parent ec18eb22e9
commit 68b77ab4e8
13 changed files with 523 additions and 434 deletions

View File

@ -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,14 +184,77 @@ 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.
keygroup Moving around
key 'Select the client to the left' $MODKEY-$LEFT || fn $key {
wmiir xwrite /tag/sel/ctl select left}
key 'Select the client to the right' $MODKEY-$RIGHT || fn $key {
wmiir xwrite /tag/sel/ctl select right}
key 'Select the client below' $MODKEY-$DOWN || fn $key {
wmiir xwrite /tag/sel/ctl select down}
key 'Select the client above' $MODKEY-$UP || fn $key {
wmiir xwrite /tag/sel/ctl select up}
key $MODKEY-Control-t || 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 'Select the stack above' $MODKEY-Control-$UP || fn $key {
wmiir xwrite /tag/sel/ctl select up stack}
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 'Move selected client to the right' $MODKEY-Shift-$RIGHT || fn $key {
wmiir xwrite /tag/sel/ctl send sel right}
key 'Move selected client down' $MODKEY-Shift-$DOWN || fn $key {
wmiir xwrite /tag/sel/ctl send sel down}
key 'Move selected client up' $MODKEY-Shift-$UP || fn $key {
wmiir xwrite /tag/sel/ctl send sel up}
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}
keygroup Changing column modes
key 'Set column to default mode' $MODKEY-d || fn $key {
wmiir xwrite /tag/sel/ctl colmode sel default-max}
key 'Toggle between floating and managed layers' $MODKEY-s || fn $key {
wmiir xwrite /tag/sel/ctl colmode sel stack-max}
key 'Set column to max mode' $MODKEY-m || fn $key {
wmiir xwrite /tag/sel/ctl colmode sel stack+max}
keygroup Running programs
key 'Open wmii actions menu' $MODKEY-a || fn $key {
Action `{wi_actions | wimenu -h $hist.action -n $histlen} &}
key 'Open program menu' $MODKEY-p || fn $key {
ifs=() { cmd = `{wimenu -h $hist.prog -n $histlen <$progs_file} }
wi_runcmd $cmd & }
key 'Launch a terminal' $MODKEY-Return || fn $key {
wi_runcmd $WMII_TERM &}
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
@ -199,66 +265,22 @@ key $MODKEY-Control-t || fn $key {
wmiir xwrite /ctl grabmod Mod3
}}
key $MODKEY-$LEFT || fn $key {
wmiir xwrite /tag/sel/ctl select left}
key $MODKEY-$RIGHT || fn $key {
wmiir xwrite /tag/sel/ctl select right}
key $MODKEY-$DOWN || fn $key {
wmiir xwrite /tag/sel/ctl select down}
key $MODKEY-$UP || fn $key {
wmiir xwrite /tag/sel/ctl select up}
key $MODKEY-Control-$DOWN || fn $key {
wmiir xwrite /tag/sel/ctl select down stack}
key $MODKEY-Control-$UP || fn $key {
wmiir xwrite /tag/sel/ctl select up stack}
key $MODKEY-Shift-$LEFT || fn $key {
wmiir xwrite /tag/sel/ctl send sel left}
key $MODKEY-Shift-$RIGHT || fn $key {
wmiir xwrite /tag/sel/ctl send sel right}
key $MODKEY-Shift-$DOWN || fn $key {
wmiir xwrite /tag/sel/ctl send sel down}
key $MODKEY-Shift-$UP || fn $key {
wmiir xwrite /tag/sel/ctl send sel up}
key $MODKEY-f || fn $key {
wmiir xwrite /client/sel/ctl Fullscreen toggle}
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 {
wmiir xwrite /tag/sel/ctl colmode sel default-max}
key $MODKEY-s || fn $key {
wmiir xwrite /tag/sel/ctl colmode sel stack-max}
key $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 {
Action `{wi_actions | wimenu -h $hist.action -n $histlen} &}
key $MODKEY-p || fn $key {
ifs=() { cmd = `{wimenu -h $hist.prog -n $histlen <$progs_file} }
wi_runcmd $cmd & }
key $MODKEY-Return || fn $key {
wi_runcmd $WMII_TERM &}
key $MODKEY-t || fn $key {
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

View File

@ -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 = ()

View File

@ -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}

View File

@ -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

View File

@ -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;

View File

@ -303,7 +303,8 @@ struct View {
#endif
/* global variables */
EXTERN struct {
typedef struct Defs Defs;
EXTERN struct Defs {
CTuple focuscolor;
CTuple normcolor;
Font* font;

View File

@ -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*);

View File

@ -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;
}
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);
found++;
}
done:
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);
ixp_respond(r, nil);
break;
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

View File

@ -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",
@ -471,6 +475,31 @@ getframe(View *v, int scrn, IxpMsg *m) {
return f;
}
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();

View File

@ -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{}
\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.
%% 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 Tupleforeground color background color border color
* ColorRGB color | RGBA color
RGB color6 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 | pixelspx
width percent of screen | pixelspx
\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

View File

@ -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

View File

@ -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 =

View File

@ -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