removed various unused crap

This commit is contained in:
Anselm R. Garbe 2006-02-10 21:08:58 +01:00
parent 8ef8918f09
commit f767ebcca8
17 changed files with 0 additions and 3009 deletions

View File

@ -1,43 +0,0 @@
.TH WMIIBAR 1 wmii-3
.SH NAME
wmiibar \- window manager improved 2 bar
.SH SYNOPSIS
.B wmiibar
.B \-s
.I socketfile
.SH DESCRIPTION
.SS Overview
.B wmiibar
is a generic and highly customizable bar for the X Window System,
originally designed for
.BR wmii (1).
It supports arbitrary sized labels with arbitrary styles on a per label
basis and with button click events.
Like wmii,
.B wmiibar
also implements a socket-based fileserver, which is accessed to configure and
interoperate with other components.
.SS Options
.TP
.BI \-s " socketfile"
specifies the socketfile that
.B wmiibar
should create.
.TP
.B \-v
prints version information to stderr, then exits.
.SS Customization
.B wmiibar
is customized through manipulating its filesystem namespace.
In the default setup of
.BR wmii (1)
the namespace of
.B wmiibar
can be found in /bar.
.SH SEE ALSO
.BR wmiifs (1),
.BR wmii (1),
.BR wmiiwm (1),
.BR wmiikeys (1),
.BR wmiimenu (1),
.BR wmiir (1)

View File

@ -1,898 +0,0 @@
/*
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#include <X11/Xproto.h>
#include <X11/Xutil.h>
#include <sys/socket.h>
#include "wmii.h"
/*
* filesystem specification
* / Droot
* /font Ffont <xlib font name>
* /defcolor Fdefcolor <#RRGGBB> <#RRGGBB> <#RRGGBB>
* /event Fevent
* /expand Fexpand id of expandable label
* /ctl Fctl command interface
* /new/ Ditem
* /1/ Ditem
* /1/data Fdata <arbitrary data which gets displayed>
* /1/color Fcolor <#RRGGBB> <#RRGGBB> <#RRGGBB>
*/
/* 8-bit qid.path.type */
enum {
Droot,
Ditem,
Fctl,
Ffont,
Fdefcolor,
Fexpand,
Fevent,
Fdata, /* data to display */
Fcolor
};
typedef struct {
unsigned short id;
char data[256];
char colstr[24];
Color color;
XRectangle rect;
} Item;
static size_t nitem = 0;
static size_t itemsz = 0;
static size_t iexpand = 0;
static Item **item = 0;
static IXPServer srv = { 0 };
static Display *dpy;
static int screen;
static char *font = nil;
static XFontStruct *xfont;
static GC gc;
static Window win;
static XRectangle brect, rect;
static Pixmap pmap;
static char defcolstr[24];
static Color defcolor;
Qid root_qid;
static void do_pend_fcall(char *event);
static char version[] = "wmiibar - " VERSION ", (C)opyright MMIV-MMVI Anselm R. Garbe\n";
static void
usage()
{
fprintf(stderr, "%s", "usage: wmiibar -a <address> [-v]\n");
exit(1);
}
static int
dummy_error_handler(Display * dpy, XErrorEvent * err)
{
return 0;
}
static Item *
new_item()
{
static unsigned int id = 1;
Item *it = cext_emallocz(sizeof(Item));
it->id = id++;
cext_strlcpy(it->colstr, defcolstr, sizeof(it->colstr));
it->color = defcolor;
item = (Item **)cext_array_attach((void **)item, it, sizeof(Item *), &itemsz);
nitem++;
return it;
}
static void
detach_item(Item *it)
{
cext_array_detach((void **)item, it, &itemsz);
nitem--;
}
static void
draw()
{
size_t i;
unsigned int w = 0;
Draw d = { 0 };
d.align = WEST;
d.gc = gc;
d.drawable = pmap;
d.rect = brect;
d.rect.y = 0;
d.font = xfont;
if(!nitem) { /* /default only */
d.color = defcolor;
blitz_drawlabel(dpy, &d);
}
else {
for(i = 0; i < nitem; i++) {
Item *it = item[i];
it->rect.x = it->rect.y = 0;
it->rect.height = brect.height;
if(i == iexpand)
continue;
it->rect.width = brect.height;
if(strlen(it->data)) {
if(!strncmp(it->data, "%m:", 3))
it->rect.width = brect.height / 2;
else
it->rect.width += XTextWidth(xfont, it->data, strlen(it->data));
}
w += it->rect.width;
}
if(w >= brect.width) {
/* failsafe mode, give all labels same width */
w = brect.width / nitem;
for(i = 0; i < nitem; i++) {
item[i]->rect.x = i * w;
item[i]->rect.width = w;
}
i--;
item[i]->rect.width = brect.width - item[i]->rect.x;
}
else {
item[iexpand]->rect.width = brect.width - w;
for(i = 1; i < nitem; i++)
item[i]->rect.x = item[i - 1]->rect.x + item[i - 1]->rect.width;
}
for(i = 0; i < nitem; i++) {
d.color = item[i]->color;
d.rect = item[i]->rect;
d.data = item[i]->data;
if(d.data && !strncmp(d.data, "%m:", 3))
blitz_drawmeter(dpy, &d);
else
blitz_drawlabel(dpy, &d);
}
}
XCopyArea(dpy, pmap, win, gc, 0, 0, brect.width, brect.height, 0, 0);
XSync(dpy, False);
}
static void
update_geometry()
{
char buf[64];
brect = rect;
brect.height = xfont->ascent + xfont->descent + 4;
brect.y = rect.height - brect.height;
XMoveResizeWindow(dpy, win, brect.x, brect.y, brect.width, brect.height);
XSync(dpy, False);
XFreePixmap(dpy, pmap);
pmap = XCreatePixmap(dpy, win, brect.width, brect.height,
DefaultDepth(dpy, screen));
XSync(dpy, False);
snprintf(buf, sizeof(buf), "NewGeometry %d %d %d %d\n", brect.x, brect.y, brect.width, brect.height);
do_pend_fcall(buf);
draw();
}
static void
handle_buttonpress(XButtonPressedEvent * e)
{
size_t i;
char buf[32];
for(i = 0; i < nitem; i++)
if(blitz_ispointinrect(e->x, e->y, &item[i]->rect)) {
snprintf(buf, sizeof(buf), "Button%dPress %d\n", e->button, i);
do_pend_fcall(buf);
}
}
static void
check_x_event(IXPConn *c)
{
XEvent e;
while(XPending(dpy)) {
XNextEvent(dpy, &e);
switch (e.type) {
case ButtonPress:
handle_buttonpress(&e.xbutton);
break;
case Expose:
if(e.xexpose.count == 0)
draw();
break;
default:
break;
}
}
}
static int
index_of_id(unsigned short id)
{
int i;
for(i = 0; i < nitem; i++)
if(item[i]->id == id)
return i;
return -1;
}
/* IXP stuff */
static unsigned long long
mkqpath(unsigned char type, unsigned short id)
{
return ((unsigned long long) id << 8) | (unsigned long long) type;
}
static unsigned char
qpath_type(unsigned long long path)
{
return path & 0xff;
}
static unsigned short
qpath_id(unsigned long long path)
{
return (path >> 8) & 0xffff;
}
static char *
qid_to_name(Qid *qid)
{
unsigned char type = qpath_type(qid->path);
unsigned short id = qpath_id(qid->path);
int i;
static char buf[32];
if(id && ((i = index_of_id(id)) == -1))
return nil;
switch(type) {
case Droot: return "/"; break;
case Ditem:
snprintf(buf, sizeof(buf), "%u", i + 1);
return buf;
break;
case Fctl: return "ctl"; break;
case Ffont: return "font"; break;
case Fdefcolor: return "defcolor"; break;
case Fexpand: return "expand"; break;
case Fdata: return "data"; break;
case Fevent: return "event"; break;
case Fcolor: return "color"; break;
default: return nil; break;
}
}
static int
name_to_type(char *name)
{
const char *err;
unsigned int i;
if(!name || !name[0] || !strncmp(name, "/", 2) || !strncmp(name, "..", 3))
return Droot;
if(!strncmp(name, "new", 4))
return Ditem;
if(!strncmp(name, "ctl", 4))
return Fctl;
if(!strncmp(name, "font", 5))
return Ffont;
if(!strncmp(name, "defcolor", 9))
return Fdefcolor;
if(!strncmp(name, "expand", 7))
return Fexpand;
if(!strncmp(name, "data", 5))
return Fdata;
if(!strncmp(name, "event", 6))
return Fevent;
if(!strncmp(name, "color", 6))
return Fcolor;
i = (unsigned short) cext_strtonum(name, 1, 0xffff, &err);
if(!err && (i - 1 <= nitem))
return Ditem;
return -1;
}
static int
mkqid(Qid *dir, char *wname, Qid *new, Bool iswalk)
{
const char *err;
unsigned short id = qpath_id(dir->path);
int i, type = name_to_type(wname);
if(id && ((i = index_of_id(id)) == -1))
return -1;
if((dir->type != IXP_QTDIR) || (type == -1))
return -1;
new->dtype = qpath_type(dir->path);
new->version = 0;
switch(type) {
case Droot:
*new = root_qid;
break;
case Ditem:
new->type = IXP_QTDIR;
if(!strncmp(wname, "new", 4)) {
/*fprintf(stderr, "mkqid iswalk=%d, wname=%s\n", iswalk, wname);*/
if(iswalk)
new->path = mkqpath(Ditem, new_item()->id);
else
new->path = mkqpath(Ditem, 0);
}
else {
i = cext_strtonum(wname, 1, 0xffff, &err);
if(err || (i - 1 >= nitem))
return -1;
new->path = mkqpath(Ditem, item[i - 1]->id);
}
break;
case Fdata:
case Fcolor:
if(i >= nitem)
return -1;
default:
new->type = IXP_QTFILE;
new->path = mkqpath(type, id);
break;
}
return 0;
}
static char *
xwalk(IXPConn *c, Fcall *fcall)
{
unsigned short nwqid = 0;
Qid dir = root_qid;
IXPMap *m;
if(!(m = ixp_server_fid2map(c, fcall->fid)))
return Enofid;
if(fcall->fid != fcall->newfid && (ixp_server_fid2map(c, fcall->newfid)))
return Enofid;
if(fcall->nwname) {
dir = m->qid;
for(nwqid = 0; (nwqid < fcall->nwname)
&& !mkqid(&dir, fcall->wname[nwqid], &fcall->wqid[nwqid], True); nwqid++) {
/*fprintf(stderr, "wname=%s nwqid=%d\n", fcall->wname[nwqid], nwqid);*/
dir = fcall->wqid[nwqid];
}
if(!nwqid)
return Enofile;
}
/* a fid will only be valid, if the walk was complete */
if(nwqid == fcall->nwname) {
if(fcall->fid != fcall->newfid) {
m = cext_emallocz(sizeof(IXPMap));
c->map = (IXPMap **)cext_array_attach((void **)c->map,
m, sizeof(IXPMap *), &c->mapsz);
}
m->qid = dir;
m->fid = fcall->newfid;
}
fcall->id = RWALK;
fcall->nwqid = nwqid;
ixp_server_respond_fcall(c, fcall);
return nil;
}
static char *
xopen(IXPConn *c, Fcall *fcall)
{
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
if(!m)
return Enofid;
if(!(fcall->mode | IXP_OREAD) && !(fcall->mode | IXP_OWRITE))
return Enomode;
fcall->id = ROPEN;
fcall->qid = m->qid;
fcall->iounit = 256;
ixp_server_respond_fcall(c, fcall);
return nil;
}
static unsigned int
mkstat(Stat *stat, Qid *dir, char *name, unsigned long long length, unsigned int mode)
{
stat->mode = mode;
stat->atime = stat->mtime = time(0);
cext_strlcpy(stat->uid, getenv("USER"), sizeof(stat->uid));
cext_strlcpy(stat->gid, getenv("USER"), sizeof(stat->gid));
cext_strlcpy(stat->muid, getenv("USER"), sizeof(stat->muid));
cext_strlcpy(stat->name, name, sizeof(stat->name));
stat->length = length;
mkqid(dir, name, &stat->qid, False);
return ixp_sizeof_stat(stat);
}
static unsigned int
type_to_stat(Stat *stat, char *name, Qid *dir)
{
int i, type = name_to_type(name);
unsigned short id = qpath_id(dir->path);
char buf[16];
if(id && ((i = index_of_id(id)) == -1))
return 0;
switch (type) {
case Droot:
case Ditem:
return mkstat(stat, dir, name, 0, DMDIR | DMREAD | DMEXEC);
break;
case Fctl:
return mkstat(stat, dir, name, 0, DMWRITE);
break;
case Fevent:
return mkstat(stat, dir, name, 0, DMREAD);
break;
case Ffont:
return mkstat(stat, dir, name, strlen(font), DMREAD | DMWRITE);
break;
case Fdefcolor:
return mkstat(stat, dir, name, 23, DMREAD | DMWRITE);
break;
case Fexpand:
snprintf(buf, sizeof(buf), "%u", iexpand + 1);
return mkstat(stat, dir, name, strlen(buf), DMREAD | DMWRITE);
break;
case Fdata:
return mkstat(stat, dir, name, (i == nitem) ? 0 : strlen(item[i]->data), DMREAD | DMWRITE);
break;
case Fcolor:
return mkstat(stat, dir, name, 23, DMREAD | DMWRITE);
break;
}
return 0;
}
static char *
xremove(IXPConn *c, Fcall *fcall)
{
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
unsigned short id = qpath_id(m->qid.path);
int i;
if(!m)
return Enofid;
if(id && ((i = qpath_id(id)) == -1))
return Enofile;
if((qpath_type(m->qid.path) == Ditem) && (i < nitem)) {
Item *it = item[i];
/* clunk */
cext_array_detach((void **)c->map, m, &c->mapsz);
free(m);
/* now detach the item */
detach_item(it);
free(it);
if(iexpand >= nitem)
iexpand = 0;
draw();
fcall->id = RREMOVE;
ixp_server_respond_fcall(c, fcall);
return nil;
}
return Enoperm;
}
static char *
xread(IXPConn *c, Fcall *fcall)
{
Stat stat;
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
unsigned short id;
unsigned char *p = fcall->data;
unsigned int len;
int i;
char buf[32];
if(!m)
return Enofid;
id = qpath_id(m->qid.path);
if(id && ((i = index_of_id(id)) == -1))
return Enofile;
fcall->count = 0;
if(fcall->offset) {
switch (qpath_type(m->qid.path)) {
case Droot:
/* jump to offset */
len = type_to_stat(&stat, "ctl", &m->qid);
len += type_to_stat(&stat, "font", &m->qid);
len += type_to_stat(&stat, "defcolor", &m->qid);
len += type_to_stat(&stat, "expand", &m->qid);
len += type_to_stat(&stat, "new", &m->qid);
len += type_to_stat(&stat, "event", &m->qid);
for(i = 0; i < nitem; i++) {
snprintf(buf, sizeof(buf), "%u", i + 1);
len += type_to_stat(&stat, buf, &m->qid);
if(len <= fcall->offset)
continue;
break;
}
/* offset found, proceeding */
for(; i < nitem; i++) {
snprintf(buf, sizeof(buf), "%u", i + 1);
len = type_to_stat(&stat, buf, &m->qid);
if(fcall->count + len > fcall->iounit)
break;
fcall->count += len;
p = ixp_enc_stat(p, &stat);
}
break;
case Fevent:
ixp_server_enqueue_fcall(c, fcall);
return nil;
break;
default:
break;
}
}
else {
switch (qpath_type(m->qid.path)) {
case Droot:
fcall->count = type_to_stat(&stat, "ctl", &m->qid);
p = ixp_enc_stat(p, &stat);
fcall->count += type_to_stat(&stat, "font", &m->qid);
p = ixp_enc_stat(p, &stat);
fcall->count += type_to_stat(&stat, "defcolor", &m->qid);
p = ixp_enc_stat(p, &stat);
fcall->count += type_to_stat(&stat, "expand", &m->qid);
p = ixp_enc_stat(p, &stat);
fcall->count += type_to_stat(&stat, "new", &m->qid);
p = ixp_enc_stat(p, &stat);
fcall->count += type_to_stat(&stat, "event", &m->qid);
p = ixp_enc_stat(p, &stat);
for(i = 0; i < nitem; i++) {
snprintf(buf, sizeof(buf), "%u", i + 1);
len = type_to_stat(&stat, buf, &m->qid);
if(fcall->count + len > fcall->iounit)
break;
fcall->count += len;
p = ixp_enc_stat(p, &stat);
}
break;
case Ditem:
if(i >= nitem)
return Enofile;
fcall->count = type_to_stat(&stat, "color", &m->qid);
p = ixp_enc_stat(p, &stat);
fcall->count += type_to_stat(&stat, "data", &m->qid);
p = ixp_enc_stat(p, &stat);
break;
case Fctl:
return Enoperm;
break;
case Ffont:
if((fcall->count = strlen(font)))
memcpy(p, font, fcall->count);
break;
case Fdefcolor:
if((fcall->count = strlen(defcolstr)))
memcpy(p, defcolstr, fcall->count);
break;
case Fexpand:
snprintf(buf, sizeof(buf), "%u", iexpand + 1);
fcall->count = strlen(buf);
memcpy(p, buf, fcall->count);
break;
case Fdata:
if(i >= nitem)
return Enofile;
if((fcall->count = strlen(item[i]->data)))
memcpy(p, item[i]->data, fcall->count);
break;
case Fcolor:
if(i >= nitem)
return Enofile;
if((fcall->count = strlen(item[i]->colstr)))
memcpy(p, item[i]->colstr, fcall->count);
break;
case Fevent:
ixp_server_enqueue_fcall(c, fcall);
return nil;
break;
default:
return "invalid read";
break;
}
}
fcall->id = RREAD;
ixp_server_respond_fcall(c, fcall);
return nil;
}
static char *
xstat(IXPConn *c, Fcall *fcall)
{
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
char *name;
if(!m)
return Enofid;
name = qid_to_name(&m->qid);
/*fprintf(stderr, "xstat: name=%s\n", name);*/
if(!type_to_stat(&fcall->stat, name, &m->qid))
return Enofile;
fcall->id = RSTAT;
ixp_server_respond_fcall(c, fcall);
return nil;
}
static char *
xwrite(IXPConn *c, Fcall *fcall)
{
char buf[256];
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
unsigned short id;
int i;
if(!m)
return Enofid;
id = qpath_id(m->qid.path);
if(id && ((i = index_of_id(id)) == -1))
return Enofile;
switch (qpath_type(m->qid.path)) {
case Fctl:
if(fcall->count == 4) {
memcpy(buf, fcall->data, 4);
buf[4] = 0;
if(!strncmp(buf, "quit", 5)) {
srv.running = 0;
break;
}
}
return Enocommand;
break;
case Ffont:
if(font)
free(font);
font = cext_emallocz(fcall->count + 1);
memcpy(font, fcall->data, fcall->count);
XFreeFont(dpy, xfont);
xfont = blitz_getfont(dpy, font);
update_geometry();
break;
case Fdefcolor:
if((fcall->count != 23)
|| (fcall->data[0] != '#') || (fcall->data[8] != '#')
|| (fcall->data[16] != '#')
)
return "wrong color format";
memcpy(defcolstr, fcall->data, fcall->count);
defcolstr[fcall->count] = 0;
blitz_loadcolor(dpy, screen, defcolstr, &defcolor);
break;
case Fexpand:
{
const char *err;
if(fcall->count && fcall->count < 16) {
memcpy(buf, fcall->data, fcall->count);
buf[fcall->count] = 0;
i = (unsigned short) cext_strtonum(buf, 1, 0xffff, &err);
if(!err && (i - 1 < nitem)) {
iexpand = i - 1;
draw();
break;
}
}
}
return Enofile;
break;
case Fdata:
{
unsigned int len = fcall->count;
if(i >= nitem)
return Enofile;
if(len >= sizeof(item[i]->data))
len = sizeof(item[i]->data) - 1;
memcpy(item[i]->data, fcall->data, len);
item[i]->data[len] = 0;
draw();
}
break;
case Fcolor:
if((i >= nitem) || (fcall->count != 23)
|| (fcall->data[0] != '#') || (fcall->data[8] != '#')
|| (fcall->data[16] != '#')
)
return "wrong color format";
memcpy(item[i]->colstr, fcall->data, fcall->count);
item[i]->colstr[fcall->count] = 0;
blitz_loadcolor(dpy, screen, item[i]->colstr, &item[i]->color);
draw();
break;
default:
return "invalid write";
break;
}
fcall->id = RWRITE;
ixp_server_respond_fcall(c, fcall);
return nil;
}
static void
do_fcall(IXPConn *c)
{
static Fcall fcall;
unsigned int msize;
char *errstr;
if((msize = ixp_server_receive_fcall(c, &fcall))) {
/*fprintf(stderr, "fcall=%d\n", fcall.id);*/
switch(fcall.id) {
case TVERSION: errstr = wmii_ixp_version(c, &fcall); break;
case TATTACH: errstr = wmii_ixp_attach(c, &fcall); break;
case TWALK: errstr = xwalk(c, &fcall); break;
case TREMOVE: errstr = xremove(c, &fcall); break;
case TOPEN: errstr = xopen(c, &fcall); break;
case TREAD: errstr = xread(c, &fcall); break;
case TWRITE: errstr = xwrite(c, &fcall); break;
case TCLUNK: errstr = wmii_ixp_clunk(c, &fcall); break;
case TSTAT: errstr = xstat(c, &fcall); break;
default: errstr = Enofunc; break;
}
if(errstr)
ixp_server_respond_error(c, &fcall, errstr);
}
check_x_event(nil);
}
static void
do_pend_fcall(char *event)
{
size_t i;
Fcall *fcall;
for(i = 0; (i < srv.connsz) && srv.conn[i]; i++) {
IXPConn *c = srv.conn[i];
/* all pending TREADs are on /event, so no qid checking necessary */
while((fcall = ixp_server_dequeue_fcall_id(c, TREAD))) {
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
unsigned char *p = fcall->data;
if(!m) {
if(ixp_server_respond_error(c, fcall, Enofid))
break;
}
else if(qpath_type(m->qid.path) == Fevent) {
fcall->count = strlen(event);
memcpy(p, event, fcall->count);
fcall->id = RREAD;
if(ixp_server_respond_fcall(c, fcall))
break;
}
free(fcall);
}
}
}
static void
new_ixp_conn(IXPConn *c)
{
int fd = ixp_accept_sock(c->fd);
if(fd >= 0)
ixp_server_open_conn(c->srv, fd, do_fcall, ixp_server_close_conn);
}
/* main */
int
main(int argc, char *argv[])
{
int i;
char *errstr;
char *address = nil;
XSetWindowAttributes wa;
/* command line args */
for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
switch (argv[i][1]) {
case 'v':
fprintf(stdout, "%s", version);
exit(0);
break;
case 'a':
if(i + 1 < argc)
address = argv[++i];
else
usage();
break;
default:
usage();
break;
}
}
if(!address)
usage();
dpy = XOpenDisplay(0);
if(!dpy) {
fprintf(stderr, "%s", "wmiibar: cannot open display\n");
exit(1);
}
XSetErrorHandler(dummy_error_handler);
screen = DefaultScreen(dpy);
i = ixp_create_sock(address, &errstr);
if(i < 0) {
fprintf(stderr, "wmiibar: fatal: %s\n", errstr);
exit(1);
}
/* IXP server */
ixp_server_open_conn(&srv, i, new_ixp_conn, ixp_server_close_conn);
root_qid.type = IXP_QTDIR;
root_qid.version = 0;
root_qid.path = mkqpath(Droot, 0);
/* X server */
ixp_server_open_conn(&srv, ConnectionNumber(dpy), check_x_event, nil);
/* default settings */
cext_strlcpy(defcolstr, BLITZ_SELCOLORS, sizeof(defcolstr));
blitz_loadcolor(dpy, screen, defcolstr, &defcolor);
/* X stuff */
font = strdup(BLITZ_FONT);
xfont = blitz_getfont(dpy, font);
wa.override_redirect = 1;
wa.background_pixmap = ParentRelative;
wa.event_mask = ExposureMask | ButtonPressMask
| SubstructureRedirectMask | SubstructureNotifyMask;
rect.x = rect.y = 0;
rect.width = DisplayWidth(dpy, screen);
rect.height = DisplayHeight(dpy, screen);
brect = rect;
brect.height = xfont->ascent + xfont->descent + 4;
brect.y = rect.height - brect.height;
win = XCreateWindow(dpy, RootWindow(dpy, screen), brect.x, brect.y,
brect.width, brect.height, 0, DefaultDepth(dpy, screen),
CopyFromParent, DefaultVisual(dpy, screen),
CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_left_ptr));
XSync(dpy, False);
gc = XCreateGC(dpy, win, 0, 0);
pmap = XCreatePixmap(dpy, win, brect.width, brect.height,
DefaultDepth(dpy, screen));
/* main loop */
XMapRaised(dpy, win);
draw();
errstr = ixp_server_loop(&srv);
if(errstr)
fprintf(stderr, "wmiibar: fatal: %s\n", errstr);
/* cleanup */
ixp_server_close(&srv);
XCloseDisplay(dpy);
return errstr ? 1 : 0;
}

View File

@ -1,38 +0,0 @@
.TH WMIIFS 1 wmii-3
.SH NAME
wmiifs \- window manager improved 2 filesystem
.SH SYNOPSIS
.B wmiifs
.B \-s
.I socketfile
.SH DESCRIPTION
.SS Overview
.B wmiifs
is a socket-based fileserver which is used for binding other fileserver
filesystems to a specific namespace. It routes filesystem accesses to
the specific fileserver and behaves to the outside as one master
filesystem.
.SS Options
.TP
.BI \-s " socketfile"
specifies the socketfile that
.B wmiifs
should create.
.TP
.B \-v
prints version information to stderr, then exits.
.SS Customization
.B wmiifs
is customized through manipulating its filesystem namespace.
In the default setup of
.BR wmii (1)
the namespace of
.B wmiifs
can be found in /.
.SH SEE ALSO
.BR wmiibar (1),
.BR wmii (1),
.BR wmiiwm (1),
.BR wmiikeys (1),
.BR wmiimenu (1),
.BR wmiir (1)

View File

@ -1,791 +0,0 @@
/*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "wmii.h"
/*
* filesystem specification
* / Droot
* /ctl Fctl command interface
* /foobar Dmount
*/
/* 8-bit qid.path.type */
enum {
Droot,
Dmount,
Fctl
};
typedef struct Bind Bind;
struct Bind {
unsigned int fid;
Fcall fcall;
IXPClient client;
IXPConn *rx;
IXPConn *tx;
};
typedef struct Mount Mount;
struct Mount {
unsigned short id;
char wname[IXP_MAX_FLEN];
char address[256];
};
Qid root_qid;
static Display *dpy;
static IXPServer srv;
static Mount **mount = nil;
static size_t mountsz = 0;
static size_t nmount = 0;
static unsigned char *msg[IXP_MAX_MSG];
static Bind **bind = nil;
static size_t bindsz = 0;
static size_t nbind = 0;
static void do_mnt_fcall(IXPConn *c);
static char version[] = "wmiifs - " VERSION ", (C)opyright MMIV-MMVI Anselm R. Garbe\n";
static char Enoserv[] = "server not found";
static void
usage()
{
fprintf(stderr, "usage: wmiifs -a <address> [-v]\n");
exit(1);
}
static Mount *
name_to_mount(char *name)
{
size_t i;
for(i = 0; i < nmount; i++)
if(!strncmp(mount[i]->wname, name, sizeof(mount[i]->wname)))
return mount[i];
return nil;
}
static Bind *
fid_to_bind(unsigned int fid)
{
size_t i;
for(i = 0; i < nbind; i++)
if(bind[i]->fid == fid)
return bind[i];
return nil;
}
static Bind *
rx_to_bind(IXPConn *c)
{
size_t i;
for(i = 0; i < nbind; i++)
if(bind[i]->rx == c)
return bind[i];
return nil;
}
static void
xunbind(Bind *b) {
cext_array_detach((void **)srv.conn, b->rx, &srv.connsz);
free(b->rx);
cext_array_detach((void **)bind, b, &bindsz);
nbind--;
ixp_client_deinit(&b->client);
if(b->tx && b->tx->close)
b->tx->close(b->tx);
free(b);
}
static void
close_rx_conn(IXPConn *c)
{
Bind *b = rx_to_bind(c);
if(!b)
return;
xunbind(b);
}
static Bind *
xbind(char *address, unsigned int fid)
{
char addr[256];
Bind *b = cext_emallocz(sizeof(Bind));
cext_strlcpy(addr, address, sizeof(addr));
if(ixp_client_init(&b->client, addr, fid) == -1) {
free(b);
return nil;
}
b->rx = ixp_server_open_conn(&srv, b->client.fd, do_mnt_fcall, close_rx_conn);
bind = (Bind **)cext_array_attach((void **)bind, b, sizeof(Bind *), &bindsz);
nbind++;
return b;
}
static void
xunmount(Mount *mnt) /* called by xremove */
{
cext_array_detach((void **)mount, mnt, &mountsz);
nmount--;
free(mnt);
}
static char *
xmount(char *arg)
{
char *address = arg;
char *p, *wname = strchr(address, ' ');
Mount *mnt;
if(!wname)
return "no mount point supplied";
*wname = 0;
wname++;
if(*wname == '/')
wname++;
p = strchr(wname, '/');
if(p)
*p = 0; /* mount name is not allowed to contain slashes */
if(!address || !wname || !*address || !*wname)
return Enoserv;
if(!(mnt = name_to_mount(wname))) {
mnt = cext_emallocz(sizeof(Mount));
cext_strlcpy(mnt->address, address, sizeof(mnt->address));
mount = (Mount **)cext_array_attach((void **)mount, mnt, sizeof(Mount *), &mountsz);
nmount++;
}
cext_strlcpy(mnt->wname, wname, sizeof(mnt->wname));
return nil;
}
static int
index_of_id(unsigned short id)
{
int i;
for(i = 0; i < nmount; i++)
if(mount[i]->id == id)
return i;
return -1;
}
/* IXP stuff */
static unsigned long long
mkqpath(unsigned char type, unsigned short id)
{
return ((unsigned long long) id << 8) | (unsigned long long) type;
}
static unsigned char
qpath_type(unsigned long long path)
{
return path & 0xff;
}
static unsigned short
qpath_id(unsigned long long path)
{
return (path >> 8) & 0xffff;
}
static char *
qid_to_name(Qid *qid)
{
unsigned char type = qpath_type(qid->path);
unsigned short id = qpath_id(qid->path);
int i;
if(id && ((i = index_of_id(id)) == -1))
return nil;
switch(type) {
case Droot: return "/"; break;
case Dmount: return mount[i]->wname; break;
case Fctl: return "ctl"; break;
default: return nil; break;
}
}
static int
name_to_type(char *name)
{
if(!name || !name[0] || !strncmp(name, "/", 2) || !strncmp(name, "..", 3))
return Droot;
if(!strncmp(name, "ctl", 4))
return Fctl;
if(name_to_mount(name))
return Dmount;
return -1;
}
static int
mkqid(Qid *dir, char *wname, Qid *new, Bool iswalk)
{
Mount *mnt;
int type = name_to_type(wname);
if((dir->type != IXP_QTDIR) || (type == -1))
return -1;
new->dtype = qpath_type(dir->path);
new->version = 0;
switch(type) {
case Droot:
*new = root_qid;
break;
case Dmount:
if(!(mnt = name_to_mount(wname)))
return -1;
new->type = IXP_QTDIR;
new->path = mkqpath(type, mnt->id);
break;
default:
new->type = IXP_QTFILE;
new->path = mkqpath(type, 0);
break;
}
return 0;
}
static unsigned int
mkstat(Stat *stat, Qid *dir, char *name, unsigned long long length, unsigned int mode)
{
stat->mode = mode;
stat->atime = stat->mtime = time(0);
cext_strlcpy(stat->uid, getenv("USER"), sizeof(stat->uid));
cext_strlcpy(stat->gid, getenv("USER"), sizeof(stat->gid));
cext_strlcpy(stat->muid, getenv("USER"), sizeof(stat->muid));
cext_strlcpy(stat->name, name, sizeof(stat->name));
stat->length = length;
mkqid(dir, name, &stat->qid, False);
return ixp_sizeof_stat(stat);
}
static unsigned int
type_to_stat(Stat *stat, char *name, Qid *dir)
{
Mount *mnt;
int type = name_to_type(name);
switch (type) {
case Droot:
return mkstat(stat, dir, name, 0, DMDIR | DMREAD | DMEXEC);
break;
case Fctl:
return mkstat(stat, dir, name, 0, DMWRITE);
break;
case Dmount:
if(!(mnt = name_to_mount(name)))
return -1;
return mkstat(stat, dir, name, 0, DMDIR | DMREAD | DMEXEC | DMMOUNT);
break;
}
return 0;
}
static void
mntrespond(IXPConn *c, Fcall *fcall)
{
Bind *b = rx_to_bind(c);
/*fprintf(stderr, "mntrespond, welcome: fcall->id=%d\n", fcall->id);*/
memcpy(&b->fcall, fcall, sizeof(Fcall));
ixp_server_respond_fcall(b->tx, &b->fcall);
}
static void
mntwalk(IXPConn *c, Fcall *fcall)
{
Qid dir = root_qid;
Bind *b = rx_to_bind(c);
unsigned int nwqid;
IXPMap *m;
if(!(m = ixp_server_fid2map(b->tx, b->fcall.fid))) {
ixp_server_respond_error(b->tx, &b->fcall, Enofid);
xunbind(b);
return;
}
if(mkqid(&dir, b->fcall.wname[0], &b->fcall.wqid[0], True) == -1) {
/*fprintf(stderr, "%s", "wmiifs: mntwalk cannot make qid\n");*/
ixp_server_respond_error(b->tx, &b->fcall, Enofile);
xunbind(b);
return;
}
dir = b->fcall.wqid[0]; /* mount point */
for(nwqid = 0; nwqid < fcall->nwqid; nwqid++)
b->fcall.wqid[nwqid + 1] = fcall->wqid[nwqid];
nwqid++;
if(!nwqid) {
/*fprintf(stderr, "%s", "wmiifs: mntwalk nwqid wrong \n");*/
ixp_server_respond_error(b->tx, &b->fcall, Enofile);
xunbind(b);
return;
}
/* a fid will only be valid, if the walk was complete */
/*fprintf(stderr, "nwqid=%d b->fcall.nwname=%d", nwqid, b->fcall.nwname);*/
if(nwqid == b->fcall.nwname) {
if(b->fcall.fid != b->fcall.newfid) {
m = cext_emallocz(sizeof(IXPMap));
b->tx->map = (IXPMap **)
cext_array_attach((void **)b->tx->map, m, sizeof(IXPMap *), &b->tx->mapsz);
}
m->qid = dir; /* mount point, even if not */
m->fid = b->fcall.newfid;
/*fprintf(stderr, "%s", "wmiifs: fffaoooo\n");*/
}
/*fprintf(stderr, "wmiifs: success mntwalk b-tx=%x m->fid = %d (b->fcall.newfid=%d)\n",
b->tx, m->fid, b->fcall.newfid);*/
b->fid = m->fid;
b->fcall.id = RWALK;
b->fcall.nwqid = nwqid;
ixp_server_respond_fcall(b->tx, &b->fcall);
}
static char *
mntrequest(Bind *b, Fcall *tx)
{
unsigned int msize;
/*fprintf(stderr, "mntrequest: welcome, tx=%x tx->id=%d fid=%d\n", b->tx, tx->id, tx->fid);*/
memcpy(&b->client.fcall, tx, sizeof(Fcall));
memcpy(&b->fcall, tx, sizeof(Fcall));
msize = ixp_fcall_to_msg(msg, &b->client.fcall, IXP_MAX_MSG);
b->client.errstr = 0;
if(ixp_send_message(b->client.fd, msg, msize, &b->client.errstr) != msize) {
xunbind(b);
return Enofile;
}
return nil;
}
static char *
xwalk(IXPConn *c, Fcall *fcall)
{
unsigned short nwqid = 0;
Qid dir = root_qid;
IXPMap *m;
Mount *mnt;
/*fprintf(stderr, "xwalk: welcome fcall->wname[0]=%s fcall->fid=%d\n", fcall->wname[0], fcall->fid);*/
if(!(m = ixp_server_fid2map(c, fcall->fid)))
return Enofid;
if(fcall->fid != fcall->newfid && (ixp_server_fid2map(c, fcall->newfid)))
return Enofid;
/*fprintf(stderr, "xwalk: fcall->nwname=%d\n", fcall->nwname);*/
if(fcall->nwname) {
dir = m->qid;
if((mnt = name_to_mount(fcall->wname[0]))) {
unsigned int i;
Bind *b;
if(!(b = xbind(mnt->address, fcall->fid)))
return Enoserv;
memcpy(&b->client.fcall, fcall, sizeof(Fcall));
memcpy(&b->fcall, fcall, sizeof(Fcall));
/*fprintf(stderr, "xwalk: sending fid=%d (newfid=%d)\n", b->client.fcall.fid, b->client.fcall.newfid);*/
b->client.fcall.nwname = fcall->nwname - 1;
for(i = 1; i < fcall->nwname; i++)
cext_strlcpy(b->client.fcall.wname[i - 1], fcall->wname[i],
sizeof(b->client.fcall.wname[i - 1]));
i = ixp_fcall_to_msg(msg, &b->client.fcall, IXP_MAX_MSG);
b->client.errstr = 0;
if(ixp_send_message(b->client.fd, msg, i, &b->client.errstr) != i) {
xunbind(b);
return Enofile;
}
b->tx = c;
return nil;
}
else {
for(nwqid = 0; (nwqid < fcall->nwname)
&& !mkqid(&dir, fcall->wname[nwqid], &fcall->wqid[nwqid], True); nwqid++) {
dir = fcall->wqid[nwqid];
}
if(!nwqid)
return Enofile;
}
}
/* a fid will only be valid, if the walk was complete */
if(nwqid == fcall->nwname) {
if(fcall->fid != fcall->newfid) {
m = cext_emallocz(sizeof(IXPMap));
c->map = (IXPMap **)cext_array_attach((void **)c->map,
m, sizeof(IXPMap *), &c->mapsz);
}
m->qid = dir;
m->fid = fcall->newfid;
}
fcall->id = RWALK;
fcall->nwqid = nwqid;
ixp_server_respond_fcall(c, fcall);
return nil;
}
static char *
xcreate(IXPConn *c, Fcall *fcall)
{
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
Bind *b;
if(!m)
return Enofid;
if((b = fid_to_bind(m->fid)))
return mntrequest(b, fcall);
return Enoperm;
}
static char *
xopen(IXPConn *c, Fcall *fcall)
{
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
Bind *b;
if(!m)
return Enofid;
if((b = fid_to_bind(m->fid)))
return mntrequest(b, fcall);
if(!(fcall->mode | IXP_OREAD) && !(fcall->mode | IXP_OWRITE))
return Enomode;
fcall->id = ROPEN;
fcall->qid = m->qid;
fcall->iounit = 2048;
ixp_server_respond_fcall(c, fcall);
return nil;
}
static void
mntclunkremove(IXPConn *c, Fcall *fcall)
{
Bind *b = rx_to_bind(c);
IXPMap *m;
if(!(m = ixp_server_fid2map(b->tx, b->fcall.fid))) {
ixp_server_respond_error(b->tx, &b->fcall, Enofid);
xunbind(b);
return;
}
cext_array_detach((void **)b->tx->map, m, &b->tx->mapsz);
free(m);
ixp_server_respond_fcall(b->tx, &b->fcall);
xunbind(b);
}
static char *
xremove(IXPConn *c, Fcall *fcall)
{
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
Bind *b;
if(!m)
return Enofid;
if((b = fid_to_bind(m->fid)))
return mntrequest(b, fcall);
return Enoperm;
}
static char *
xread(IXPConn *c, Fcall *fcall)
{
Stat stat;
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
unsigned short id;
unsigned char *p = fcall->data;
unsigned int len = 0;
Bind *b;
int i;
if(!m)
return Enofid;
if((b = fid_to_bind(m->fid)))
return mntrequest(b, fcall);
id = qpath_id(m->qid.path);
if(id && ((i = index_of_id(id)) == -1))
return Enofile;
fcall->count = 0;
if(fcall->offset) {
switch (qpath_type(m->qid.path)) {
case Droot:
/* jump to offset */
len = type_to_stat(&stat, "ctl", &m->qid);
for(i = 0; i < nmount; i++) {
len += type_to_stat(&stat, mount[i]->wname, &m->qid);
if(len <= fcall->offset)
continue;
break;
}
/* offset found, proceeding */
for(; i < nmount; i++) {
len = type_to_stat(&stat, mount[i]->wname, &m->qid);
if(fcall->count + len > fcall->iounit)
break;
fcall->count += len;
p = ixp_enc_stat(p, &stat);
}
break;
default:
break;
}
}
else {
switch (qpath_type(m->qid.path)) {
case Droot:
fcall->count = type_to_stat(&stat, "ctl", &m->qid);
p = ixp_enc_stat(p, &stat);
for(i = 0; i < nmount; i++) {
len = type_to_stat(&stat, mount[i]->wname, &m->qid);
if(fcall->count + len > fcall->iounit)
break;
fcall->count += len;
p = ixp_enc_stat(p, &stat);
}
break;
case Dmount:
/* TODO: */
break;
case Fctl:
return Enoperm;
break;
default:
return "invalid read";
break;
}
}
fcall->id = RREAD;
ixp_server_respond_fcall(c, fcall);
return nil;
}
static char *
xstat(IXPConn *c, Fcall *fcall)
{
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
Bind *b;
char *name;
/*fprintf(stderr, "xstat: welcome, c=%x fcall->fid=%d\n", c, fcall->fid);*/
if(!m)
return Enofid;
/*fprintf(stderr, "xstat: now fetching bind, fcall->fid=%d\n", fcall->fid);*/
if((b = fid_to_bind(m->fid)))
return mntrequest(b, fcall);
name = qid_to_name(&m->qid);
if(!type_to_stat(&fcall->stat, name, &m->qid))
return Enofile;
fcall->id = RSTAT;
ixp_server_respond_fcall(c, fcall);
return nil;
}
static char *
xwrite(IXPConn *c, Fcall *fcall)
{
char *p, buf[256];
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
Bind *b;
if(!m)
return Enofid;
if((b = fid_to_bind(m->fid)))
return mntrequest(b, fcall);
switch (qpath_type(m->qid.path)) {
case Fctl:
if(fcall->count > sizeof(buf) - 1)
return Enocommand;
memcpy(buf, fcall->data, fcall->count);
buf[fcall->count] = 0;
if(!strncmp(buf, "quit", 5)) {
srv.running = 0;
break;
}
else if(!strncmp(buf, "mount ", 6)) {
p = xmount(&buf[6]);
if(p)
return p;
break;
}
else if(!strncmp(buf, "unmount ", 8)) {
Mount *mnt;
char *mstr = &buf[8];
if(*mstr == '/')
mstr++;
p = strchr(mstr, '/');
if(p)
*p = 0; /* mount name is not allowed to contain slashes */
if((mnt = name_to_mount(mstr))) {
xunmount(mnt);
break;
}
return "no such mount point";
}
return Enocommand;
break;
default:
return "invalid write";
break;
}
fcall->id = RWRITE;
ixp_server_respond_fcall(c, fcall);
return nil;
}
char *
xclunk(IXPConn *c, Fcall *fcall)
{
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
Bind *b;
if(!m)
return Enofid;
if((b = fid_to_bind(m->fid)))
return mntrequest(b, fcall);
cext_array_detach((void **)c->map, m, &c->mapsz);
free(m);
fcall->id = RCLUNK;
ixp_server_respond_fcall(c, fcall);
return nil;
}
static void
do_mnt_fcall(IXPConn *c)
{
static Fcall fcall;
unsigned int msize;
if((msize = ixp_server_receive_fcall(c, &fcall))) {
/*fprintf(stderr, "mntfcall=%d\n", fcall.id);*/
switch(fcall.id) {
case RWALK: mntwalk(c, &fcall); break;
case RREMOVE:
case RCLUNK: mntclunkremove(c, &fcall); break;
case RCREATE:
case ROPEN:
case RREAD:
case RWRITE:
case RSTAT:
case RERROR: mntrespond(c, &fcall); break;
}
}
}
static void
do_fcall(IXPConn *c)
{
static Fcall fcall;
unsigned int msize;
char *errstr;
if((msize = ixp_server_receive_fcall(c, &fcall))) {
/*fprintf(stderr, "locfcall=%d\n", fcall.id);*/
switch(fcall.id) {
case TVERSION: errstr = wmii_ixp_version(c, &fcall); break;
case TATTACH: errstr = wmii_ixp_attach(c, &fcall); break;
case TWALK: errstr = xwalk(c, &fcall); break;
case TREMOVE: errstr = xremove(c, &fcall); break;
case TCREATE: errstr = xcreate(c, &fcall); break;
case TOPEN: errstr = xopen(c, &fcall); break;
case TREAD: errstr = xread(c, &fcall); break;
case TWRITE: errstr = xwrite(c, &fcall); break;
case TCLUNK: errstr = xclunk(c, &fcall); break;
case TSTAT: errstr = xstat(c, &fcall); break;
default: errstr = Enofunc; break;
}
if(errstr)
ixp_server_respond_error(c, &fcall, errstr);
}
}
static void
new_ixp_conn(IXPConn *c)
{
int fd = ixp_accept_sock(c->fd);
if(fd >= 0)
ixp_server_open_conn(c->srv, fd, do_fcall, ixp_server_close_conn);
}
static void
check_x_event(IXPConn *c)
{
XEvent ev;
while(XPending(dpy))
XNextEvent(dpy, &ev);
/* why check them? because X won't kill wmiifs when X dies */
}
/* main */
int
main(int argc, char *argv[])
{
int i;
char *errstr;
char *address = nil;
/* command line args */
for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
switch (argv[i][1]) {
case 'v':
fprintf(stdout, "%s", version);
exit(0);
break;
case 'a':
if(i + 1 < argc)
address = argv[++i];
else
usage();
break;
default:
usage();
break;
}
}
/* just for the case X crashes/gets quit */
dpy = XOpenDisplay(0);
if(!dpy) {
fprintf(stderr, "%s", "wmiifs: cannot open display\n");
exit(1);
}
i = ixp_create_sock(address, &errstr);
if(i < 0) {
fprintf(stderr, "wmiifs: fatal: %s\n", errstr);
exit(1);
}
/* IXP server */
ixp_server_open_conn(&srv, i, new_ixp_conn, ixp_server_close_conn);
root_qid.type = IXP_QTDIR;
root_qid.version = 0;
root_qid.path = mkqpath(Droot, 0);
/* X server */
ixp_server_open_conn(&srv, ConnectionNumber(dpy), check_x_event, nil);
/* main loop */
errstr = ixp_server_loop(&srv);
if(errstr)
fprintf(stderr, "wmiibar: fatal: %s\n", errstr);
/* cleanup */
ixp_server_close(&srv);
XCloseDisplay(dpy);
return errstr ? 1 : 0;
}

View File

@ -1,45 +0,0 @@
.TH WMIIKEYS 1 wmii-3
.SH NAME
wmiikeys \- window manager improved 2 keys
.SH SYNOPSIS
.B wmiikeys
.B \-s
.I socketfile
.SH DESCRIPTION
.SS Overview
.B wmiikeys
is a generic, highly customizable, and efficient key grabbing utility for the
X Window System, originally designed for
.BR wmii (1).
It is similar to xbindkeys, but provides more flexibility and comes
with equivalent features like the ratpoison keyboard control allows.
It supports arbitrary, user defined shortcuts which are bound to
arbitrary actions.
Like wmii,
.B wmiikeys
also implements a socket-based fileserver, which is accessed to configure and
interact with other components.
.SS Options
.TP
.BI \-s " socketfile"
specifies the socketfile that
.B wmiikeys
should create.
.TP
.B \-v
prints version information to stderr, then exits.
.SS Customization
.B wmiikeys
is customized through manipulating its filesystem namespace.
In the default setup of
.BR wmii (1)
the namespace of
.B wmiikeys
can be found in /keys.
.SH SEE ALSO
.BR wmiibar (1),
.BR wmiifs (1),
.BR wmii (1),
.BR wmiiwm (1),
.BR wmiimenu (1),
.BR wmiir (1)

View File

@ -1,814 +0,0 @@
/*
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <time.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#include <X11/Xproto.h>
#include <X11/Xutil.h>
#include "wmii.h"
/*
* filesystem specification
* / Droot
* /ctl Fctl command interface
* /grab Fgrab setup interface
* /event Fevent read for receiving key presses
* /foo Fkey key file
*/
/* 8-bit qid.path.type */
enum {
Droot,
Fctl,
Fgrab,
Fevent,
Fkey
};
typedef struct Key Key;
struct Key {
unsigned short id;
char name[128];
unsigned long mod;
KeyCode key;
Key *next;
};
static IXPServer srv;
static Display *dpy;
static Window root;
static Key **key = nil;
static size_t keysz = 0;
static size_t nkey = 0;
static unsigned int num_lock_mask, valid_mask;
Qid root_qid;
static char version[] = "wmiikeys - " VERSION ", (C)opyright MMIV-MMVI Anselm R. Garbe\n";
static void do_pend_fcall(char *event);
static void
usage()
{
fprintf(stderr, "%s", "usage: wmiikeys [-a <address>] [-v]\n");
exit(1);
}
/* X stuff */
static void
grab_key(Key *k)
{
XGrabKey(dpy, k->key, k->mod, root,
True, GrabModeAsync, GrabModeAsync);
if(num_lock_mask) {
XGrabKey(dpy, k->key, k->mod | num_lock_mask, root,
True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, k->key, k->mod | num_lock_mask | LockMask, root,
True, GrabModeAsync, GrabModeAsync);
}
XSync(dpy, False);
}
static void
ungrab_key(Key *k)
{
XUngrabKey(dpy, k->key, k->mod, root);
if(num_lock_mask) {
XUngrabKey(dpy, k->key, k->mod | num_lock_mask, root);
XUngrabKey(dpy, k->key, k->mod | num_lock_mask | LockMask, root);
}
XSync(dpy, False);
}
static Key *
create_key(char *name)
{
char buf[128];
char *seq[8];
char *key;
size_t i, toks;
static unsigned short id = 1;
Key *k = 0, *r = 0;
cext_strlcpy(buf, name, sizeof(buf));
toks = cext_tokenize(seq, 8, buf, ',');
for(i = 0; i < toks; i++) {
if(!k)
r = k = cext_emallocz(sizeof(Key));
else {
k->next = cext_emallocz(sizeof(Key));
k = k->next;
}
cext_strlcpy(k->name, name, sizeof(k->name));
key = strrchr(seq[i], '-');
if(key)
key++;
else
key = seq[i];
k->key = XKeysymToKeycode(dpy, XStringToKeysym(key));
k->mod = blitz_strtomod(seq[i]);
}
r->id = id++;
return r;
}
static void
destroy_key(Key *k)
{
if(k->next)
destroy_key(k->next);
free(k);
}
static void
next_keystroke(unsigned long *mod, KeyCode *key)
{
XEvent e;
KeySym sym;
*mod = 0;
do {
XMaskEvent(dpy, KeyPressMask, &e);
*mod |= e.xkey.state & valid_mask;
*key = (KeyCode) e.xkey.keycode;
sym = XKeycodeToKeysym(dpy, e.xkey.keycode, 0);
} while(IsModifierKey(sym));
}
static void
emulate_key_press(unsigned long mod, KeyCode key)
{
XEvent e;
Window client_win;
int revert;
XGetInputFocus(dpy, &client_win, &revert);
e.xkey.type = KeyPress;
e.xkey.time = CurrentTime;
e.xkey.window = client_win;
e.xkey.display = dpy;
e.xkey.state = mod;
e.xkey.keycode = key;
XSendEvent(dpy, client_win, True, KeyPressMask, &e);
e.xkey.type = KeyRelease;
XSendEvent(dpy, client_win, True, KeyReleaseMask, &e);
XSync(dpy, False);
}
static Key **
match_keys(Key **t, size_t n, unsigned long mod, KeyCode keycode, Bool next, size_t *nres)
{
Key **result = nil;
size_t ressz = 0;
size_t i = 0;
*nres = 0;
for(i = 0; i < n; i++) {
Key *k = next ? t[i]->next : t[i];
if(k && (k->mod == mod) && (k->key == keycode)) {
result = (Key **)cext_array_attach((void **)result, k, sizeof(Key *), &ressz);
(*nres)++;
}
}
return result;
}
static void
handle_key_seq(Window w, Key **done, size_t ndone)
{
unsigned long mod;
KeyCode key;
Key **found = nil;
size_t nfound = 0;
char buf[128];
next_keystroke(&mod, &key);
found = match_keys(done, ndone, mod, key, True, &nfound);
if((done[0]->mod == mod) && (done[0]->key == key))
emulate_key_press(mod, key); /* double key */
else {
switch(nfound) {
case 0:
XBell(dpy, 0);
return; /* grabbed but not found */
case 1:
if(!found[0]->next) {
snprintf(buf, sizeof(buf), "%s\n", found[0]->name);
do_pend_fcall(buf);
break;
}
default:
handle_key_seq(w, found, nfound);
break;
}
}
free(found);
}
static void
handle_key(Window w, unsigned long mod, KeyCode keycode)
{
size_t nfound;
char buf[128];
Key **found = match_keys(key, nkey, mod, keycode, False, &nfound);
switch(nfound) {
case 0:
XBell(dpy, 0);
return; /* grabbed but not found */
case 1:
if(!found[0]->next) {
snprintf(buf, sizeof(buf), "%s\n", found[0]->name);
do_pend_fcall(buf);
break;
}
default:
XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
handle_key_seq(w, found, nfound);
XUngrabKeyboard(dpy, CurrentTime);
XSync(dpy, False);
break;
}
free(found);
}
static void
check_x_event(IXPConn *c)
{
XEvent ev;
while(XPending(dpy)) {
XNextEvent(dpy, &ev);
switch (ev.type) {
case KeyPress:
ev.xkey.state &= valid_mask;
handle_key(root, ev.xkey.state, (KeyCode) ev.xkey.keycode);
break;
case KeymapNotify:
{
size_t i;
for(i = 0; i < nkey; i++) {
ungrab_key(key[i]);
grab_key(key[i]);
}
}
break;
default:
break;
}
}
}
static int
dummy_error_handler(Display * dpy, XErrorEvent * err)
{
return 0;
}
static Key *
key_of_name(char *name)
{
size_t i;
for(i = 0; i < nkey; i++)
if(!strncmp(key[i]->name, name, sizeof(key[i]->name)))
return key[i];
return nil;
}
static int
index_of_id(unsigned short id)
{
int i;
for(i = 0; i < nkey; i++)
if(key[i]->id == id)
return i;
return -1;
}
/* IXP stuff */
static unsigned long long
mkqpath(unsigned char type, unsigned short id)
{
return ((unsigned long long) id << 8) | (unsigned long long) type;
}
static unsigned char
qpath_type(unsigned long long path)
{
return path & 0xff;
}
static unsigned short
qpath_id(unsigned long long path)
{
return (path >> 8) & 0xffff;
}
static char *
qid_to_name(Qid *qid)
{
unsigned char type = qpath_type(qid->path);
unsigned short id = qpath_id(qid->path);
int i;
if(id && ((i = index_of_id(id)) == -1))
return nil;
switch(type) {
case Droot: return "/"; break;
case Fctl: return "ctl"; break;
case Fgrab: return "grab"; break;
case Fevent: return "event"; break;
case Fkey: return key[i]->name; break;
default: return nil; break;
}
}
static int
name_to_type(char *name)
{
if(!name || !name[0] || !strncmp(name, "/", 2) || !strncmp(name, "..", 3))
return Droot;
if(!strncmp(name, "ctl", 4))
return Fctl;
if(!strncmp(name, "grab", 5))
return Fgrab;
if(!strncmp(name, "event", 6))
return Fevent;
if(key_of_name(name))
return Fkey;
return -1;
}
static int
mkqid(Qid *dir, char *wname, Qid *new, Bool iswalk)
{
Key *k;
int type = name_to_type(wname);
if((dir->type != IXP_QTDIR) || (type == -1))
return -1;
new->dtype = qpath_type(dir->path);
new->version = 0;
switch(type) {
case Droot:
*new = root_qid;
break;
case Fkey:
if(!(k = key_of_name(wname)))
return -1;
new->type = IXP_QTFILE;
new->path = mkqpath(type, k->id);
break;
default:
new->type = IXP_QTFILE;
new->path = mkqpath(type, 0);
break;
}
return 0;
}
static char *
xwalk(IXPConn *c, Fcall *fcall)
{
unsigned short nwqid = 0;
Qid dir = root_qid;
IXPMap *m;
if(!(m = ixp_server_fid2map(c, fcall->fid)))
return Enofid;
if(fcall->fid != fcall->newfid && (ixp_server_fid2map(c, fcall->newfid)))
return Enofid;
if(fcall->nwname) {
dir = m->qid;
for(nwqid = 0; (nwqid < fcall->nwname)
&& !mkqid(&dir, fcall->wname[nwqid], &fcall->wqid[nwqid], True); nwqid++) {
/*fprintf(stderr, "wname=%s nwqid=%d\n", fcall->wname[nwqid], nwqid);*/
dir = fcall->wqid[nwqid];
}
if(!nwqid)
return Enofile;
}
/* a fid will only be valid, if the walk was complete */
if(nwqid == fcall->nwname) {
if(fcall->fid != fcall->newfid) {
m = cext_emallocz(sizeof(IXPMap));
c->map = (IXPMap **)cext_array_attach((void **)c->map,
m, sizeof(IXPMap *), &c->mapsz);
}
m->qid = dir;
m->fid = fcall->newfid;
}
fcall->id = RWALK;
fcall->nwqid = nwqid;
ixp_server_respond_fcall(c, fcall);
return nil;
}
static char *
xopen(IXPConn *c, Fcall *fcall)
{
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
if(!m)
return Enofid;
if(!(fcall->mode | IXP_OREAD) && !(fcall->mode | IXP_OWRITE))
return Enomode;
fcall->id = ROPEN;
fcall->qid = m->qid;
fcall->iounit = 2048;
ixp_server_respond_fcall(c, fcall);
return nil;
}
static unsigned int
mkstat(Stat *stat, Qid *dir, char *name, unsigned long long length, unsigned int mode)
{
stat->mode = mode;
stat->atime = stat->mtime = time(0);
cext_strlcpy(stat->uid, getenv("USER"), sizeof(stat->uid));
cext_strlcpy(stat->gid, getenv("USER"), sizeof(stat->gid));
cext_strlcpy(stat->muid, getenv("USER"), sizeof(stat->muid));
cext_strlcpy(stat->name, name, sizeof(stat->name));
stat->length = length;
mkqid(dir, name, &stat->qid, False);
return ixp_sizeof_stat(stat);
}
static unsigned int
type_to_stat(Stat *stat, char *name, Qid *dir)
{
int type = name_to_type(name);
switch (type) {
case Droot:
case Fctl:
case Fgrab:
return mkstat(stat, dir, name, 0, DMWRITE);
break;
case Fevent:
return mkstat(stat, dir, name, 0, DMREAD);
break;
case Fkey:
return mkstat(stat, dir, name, 0, 0);
break;
}
return 0;
}
static char *
xremove(IXPConn *c, Fcall *fcall)
{
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
unsigned short id = qpath_id(m->qid.path);
int i;
if(!m)
return Enofid;
if(id && ((i = qpath_id(id)) == -1))
return Enofile;
if((qpath_type(m->qid.path) == Fkey) && (i < nkey)) {
Key *k = key[i];
/* clunk */
cext_array_detach((void **)c->map, m, &c->mapsz);
free(m);
/* now detach the item */
cext_array_detach((void **)key, k, &keysz);
nkey--;
destroy_key(k);
fcall->id = RREMOVE;
ixp_server_respond_fcall(c, fcall);
return nil;
}
return Enoperm;
}
static char *
xread(IXPConn *c, Fcall *fcall)
{
Stat stat;
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
unsigned short id;
unsigned char *p = fcall->data;
unsigned int len = 0;
int i;
if(!m)
return Enofid;
id = qpath_id(m->qid.path);
if(id && ((i = index_of_id(id)) == -1))
return Enofile;
fcall->count = 0;
if(fcall->offset) {
switch (qpath_type(m->qid.path)) {
case Droot:
/* jump to offset */
len = type_to_stat(&stat, "ctl", &m->qid);
len += type_to_stat(&stat, "grab", &m->qid);
len += type_to_stat(&stat, "event", &m->qid);
for(i = 0; i < nkey; i++) {
len += type_to_stat(&stat, key[i]->name, &m->qid);
fprintf(stderr, "len=%d <= fcall->offset=%lld\n", len, fcall->offset);
if(len <= fcall->offset)
continue;
break;
}
/* offset found, proceeding */
for(; i < nkey; i++) {
fprintf(stderr, "offset xread %s\n", key[i]->name);
len = type_to_stat(&stat, key[i]->name, &m->qid);
if(fcall->count + len > fcall->iounit)
break;
fcall->count += len;
p = ixp_enc_stat(p, &stat);
}
break;
case Fevent:
ixp_server_enqueue_fcall(c, fcall);
return nil;
default:
break;
}
}
else {
switch (qpath_type(m->qid.path)) {
case Droot:
fcall->count = type_to_stat(&stat, "ctl", &m->qid);
p = ixp_enc_stat(p, &stat);
fcall->count += type_to_stat(&stat, "grab", &m->qid);
p = ixp_enc_stat(p, &stat);
fcall->count += type_to_stat(&stat, "event", &m->qid);
p = ixp_enc_stat(p, &stat);
for(i = 0; i < nkey; i++) {
fprintf(stderr, "normal xread %s\n", key[i]->name);
len = type_to_stat(&stat, key[i]->name, &m->qid);
if(fcall->count + len > fcall->iounit)
break;
fcall->count += len;
p = ixp_enc_stat(p, &stat);
}
break;
case Fctl:
case Fevent:
ixp_server_enqueue_fcall(c, fcall);
return nil;
default:
return Enoperm;
break;
}
}
fcall->id = RREAD;
ixp_server_respond_fcall(c, fcall);
return nil;
}
static char *
xstat(IXPConn *c, Fcall *fcall)
{
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
char *name;
if(!m)
return Enofid;
name = qid_to_name(&m->qid);
/*fprintf(stderr, "xstat: name=%s\n", name);*/
if(!type_to_stat(&fcall->stat, name, &m->qid))
return Enofile;
fcall->id = RSTAT;
ixp_server_respond_fcall(c, fcall);
return nil;
}
static char *
xwrite(IXPConn *c, Fcall *fcall)
{
char buf[128];
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
unsigned short id;
int i;
if(!m)
return Enofid;
id = qpath_id(m->qid.path);
if(id && ((i = index_of_id(id)) == -1))
return Enofile;
switch (qpath_type(m->qid.path)) {
case Fctl:
if(fcall->count == 4) {
memcpy(buf, fcall->data, 4);
buf[4] = 0;
if(!strncmp(buf, "quit", 5)) {
srv.running = 0;
break;
}
}
return Enocommand;
break;
case Fgrab:
if(fcall->count > 2048)
return Enoperm;
{
static size_t lastcount;
static char last[2048]; /* iounit */
char fcallbuf[2048], tmp[2048]; /* iounit */
char *p1, *p2;
Key *k;
if(!fcall->offset) {
while(nkey) {
Key *k = key[0];
ungrab_key(k);
cext_array_detach((void **)key, k, &keysz);
nkey--;
destroy_key(k);
}
}
if(!fcall->count)
break;
memcpy(fcallbuf, fcall->data, fcall->count);
fcallbuf[fcall->count] = 0;
if(fcall->offset) {
p1 = strrchr(last, '\n');
p2 = strchr(fcallbuf, '\n');
memcpy(tmp, p1, lastcount - (p1 - last));
memcpy(tmp + (lastcount - (p1 - last)), p2, p2 - fcallbuf);
tmp[(lastcount - (p1 - last)) + (p2 - fcallbuf)] = 0;
k = create_key(tmp);
key = (Key **)cext_array_attach((void **)key, k, sizeof(Key *), &keysz);
nkey++;
grab_key(k);
}
else p2 = fcallbuf;
lastcount = fcall->count;
memcpy(last, fcall->data, fcall->count);
while(p2 - fcallbuf < fcall->count) {
p1 = strchr(p2, '\n');
if(!p1)
return "cannot grab, no \n supplied";
*p1 = 0;
k = create_key(p2);
key = (Key **)cext_array_attach((void **)key, k, sizeof(Key *), &keysz);
nkey++;
grab_key(k);
*p1 = '\n';
p2 = ++p1;
}
lastcount = fcall->count;
memcpy(last, fcall->data, fcall->count);
}
break;
default:
return Enoperm;
break;
}
fcall->id = RWRITE;
ixp_server_respond_fcall(c, fcall);
return nil;
}
static void
do_fcall(IXPConn *c)
{
static Fcall fcall;
unsigned int msize;
char *errstr;
if((msize = ixp_server_receive_fcall(c, &fcall))) {
/*fprintf(stderr, "fcall=%d\n", fcall.id);*/
switch(fcall.id) {
case TVERSION: errstr = wmii_ixp_version(c, &fcall); break;
case TATTACH: errstr = wmii_ixp_attach(c, &fcall); break;
case TWALK: errstr = xwalk(c, &fcall); break;
case TREMOVE: errstr = xremove(c, &fcall); break;
case TOPEN: errstr = xopen(c, &fcall); break;
case TREAD: errstr = xread(c, &fcall); break;
case TWRITE: errstr = xwrite(c, &fcall); break;
case TCLUNK: errstr = wmii_ixp_clunk(c, &fcall); break;
case TSTAT: errstr = xstat(c, &fcall); break;
default: errstr = Enofunc; break;
}
if(errstr)
ixp_server_respond_error(c, &fcall, errstr);
}
check_x_event(nil);
}
static void
do_pend_fcall(char *event)
{
size_t i;
Fcall *fcall;
for(i = 0; (i < srv.connsz) && srv.conn[i]; i++) {
IXPConn *c = srv.conn[i];
/* all pending TREADs are on /event, so no qid checking necessary */
while((fcall = ixp_server_dequeue_fcall_id(c, TREAD))) {
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
unsigned char *p = fcall->data;
if(!m) {
if(ixp_server_respond_error(c, fcall, Enofid))
break;
}
else if(qpath_type(m->qid.path) == Fevent) {
fcall->count = strlen(event);
memcpy(p, event, fcall->count);
fcall->id = RREAD;
if(ixp_server_respond_fcall(c, fcall))
break;
}
free(fcall);
}
}
}
static void
new_ixp_conn(IXPConn *c)
{
int fd = ixp_accept_sock(c->fd);
if(fd >= 0)
ixp_server_open_conn(c->srv, fd, do_fcall, ixp_server_close_conn);
}
/* main */
int
main(int argc, char *argv[])
{
int i;
char *errstr;
char *address = nil;
/* command line args */
for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
switch (argv[i][1]) {
case 'v':
fprintf(stdout, "%s", version);
exit(0);
break;
case 'a':
if(i + 1 < argc)
address = argv[++i];
else
usage();
break;
default:
usage();
break;
}
}
if(!address)
usage();
dpy = XOpenDisplay(0);
if(!dpy) {
fprintf(stderr, "%s", "wmiikeys: cannot open display\n");
exit(1);
}
XSetErrorHandler(dummy_error_handler);
i = ixp_create_sock(address, &errstr);
if(i < 0) {
fprintf(stderr, "wmiibar: fatal: %s\n", errstr);
exit(1);
}
/* IXP server */
ixp_server_open_conn(&srv, i, new_ixp_conn, ixp_server_close_conn);
root_qid.type = IXP_QTDIR;
root_qid.version = 0;
root_qid.path = mkqpath(Droot, 0);
/* X server */
ixp_server_open_conn(&srv, ConnectionNumber(dpy), check_x_event, nil);
root = RootWindow(dpy, DefaultScreen(dpy));
wmii_init_lock_modifiers(dpy, &valid_mask, &num_lock_mask);
/* main loop */
errstr = ixp_server_loop(&srv);
if(errstr)
fprintf(stderr, "wmiibar: fatal: %s\n", errstr);
/* cleanup */
ixp_server_close(&srv);
XCloseDisplay(dpy);
return errstr ? 1 : 0;
}

View File

@ -1,28 +0,0 @@
/*
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include <string.h>
#include "blitz.h"
unsigned long blitz_strtomod(char *val)
{
unsigned long mod = 0;
if (strstr(val, "Shift"))
mod |= ShiftMask;
if (strstr(val, "Control"))
mod |= ControlMask;
if (strstr(val, "Mod1") || strstr(val, "Alt"))
mod |= Mod1Mask;
if (strstr(val, "Mod2"))
mod |= Mod2Mask;
if (strstr(val, "Mod3"))
mod |= Mod3Mask;
if (strstr(val, "Mod4"))
mod |= Mod4Mask;
if (strstr(val, "Mod5"))
mod |= Mod5Mask;
return mod;
}

View File

@ -1,27 +0,0 @@
/*
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "blitz.h"
/* free the result manually! */
char *blitz_buttontostr(unsigned int button)
{
char result[8];
result[0] = 0;
snprintf(result, 8, "Button%ud", button - Button1);
return cext_estrdup(result);
}
unsigned int blitz_strtobutton(char *val)
{
unsigned int res = 0;
if (val && strlen(val) > 6 && !strncmp(val, "Button", 6))
res = blitz_strtonum(&val[6], 1, 5) + Button1;
return res;
}

View File

@ -1,17 +0,0 @@
/*
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include <stdio.h>
#include "blitz.h"
long long blitz_strtonum(const char *numstr, long long minval, long long maxval)
{
const char *errstr;
long long ret = cext_strtonum(numstr, minval, maxval, &errstr);
if (errstr)
fprintf(stderr, "liblitz: cannot convert '%s' into integer: %s [%lld..%lld]\n", numstr, errstr, minval, maxval);
return ret;
}

View File

@ -1,26 +0,0 @@
# libwmii - mediator lib for wmii
# (C)opyright MMIV-MMVI Anselm R. Garbe
include ../config.mk
CFLAGS += -I../liblitz -I../libixp -I../libcext
LDFLAGS += -L../liblitz -llitz -L../libixp -lixp -L../libcext -lcext
SRC = ixp.c spawn.c wm.c
OBJ = ${SRC:.c=.o}
all: libwmii
@echo built libwmii
.c.o:
@echo CC $<
@${CC} -c ${CFLAGS} $<
libwmii: ${OBJ}
@echo AR $@.a
@${AR} $@.a ${OBJ}
@${RANLIB} $@.a
clean:
rm -f libwmii.a *.o

View File

@ -1,40 +0,0 @@
/*
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "wmii.h"
static void (*sigchld)() = 0;
static void
sig_handler(int signal)
{
switch (signal)
{
case SIGINT:
case SIGTERM:
case SIGHUP:
if(sigchld)
sigchld();
break;
case SIGCHLD:
wait(0);
break;
}
}
void
wmii_signal(void (*sigchld_handler)())
{
sigchld = sigchld_handler;
signal(SIGTERM, sig_handler);
signal(SIGINT, sig_handler);
signal(SIGHUP, sig_handler);
signal(SIGCHLD, sig_handler);
}

View File

@ -1,27 +0,0 @@
/*
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include "wmii.h"
void
wmii_spawn(void *dpy, char *cmd)
{
if(fork() == 0) {
if(fork() == 0) {
setsid();
close(ConnectionNumber(dpy));
execlp("rc", "rc", "-c", cmd, (char *) 0);
perror("failed");
exit(1);
}
exit(0);
}
wait(0);
}

View File

@ -1,81 +0,0 @@
/*
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include "blitz.h"
int
wmii_property(Display * dpy, Window w, Atom a, Atom t, long l,
unsigned char **prop)
{
Atom real;
int format;
unsigned long res, extra;
int status;
status =
XGetWindowProperty(dpy, w, a, 0L, l, False, t, &real, &format,
&res, &extra, prop);
if(status != Success || *prop == 0) {
return 0;
}
if(res == 0) {
free((void *) *prop);
}
return res;
}
void
wmii_send_message(Display * dpy, Window w, Atom a, long value)
{
XEvent e;
e.type = ClientMessage;
e.xclient.window = w;
e.xclient.message_type = a;
e.xclient.format = 32;
e.xclient.data.l[0] = value;
e.xclient.data.l[1] = CurrentTime;
XSendEvent(dpy, w, False, NoEventMask, &e);
XSync(dpy, False);
}
#define NUM_MASKS 8
void
wmii_init_lock_modifiers(Display * dpy, unsigned int *valid_mask,
unsigned int *num_lock_mask)
{
XModifierKeymap *modmap;
KeyCode num_lock;
static int masks[NUM_MASKS] = {
ShiftMask, LockMask, ControlMask, Mod1Mask,
Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
};
int i;
*num_lock_mask = 0;
modmap = XGetModifierMapping(dpy);
num_lock = XKeysymToKeycode(dpy, XStringToKeysym("Num_Lock"));
if(modmap && modmap->max_keypermod > 0) {
int max = NUM_MASKS * modmap->max_keypermod;
for(i = 0; i < max; i++) {
if(num_lock && (modmap->modifiermap[i] == num_lock)) {
*num_lock_mask = masks[i / modmap->max_keypermod];
}
}
}
XFreeModifiermap(modmap);
*valid_mask = 255 & ~(*num_lock_mask | LockMask);
}

View File

@ -1,31 +0,0 @@
/*
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include "ixp.h"
#include "blitz.h"
/* ixp.c */
#define E9pversion "9P version not supported"
#define Enoperm "permission denied"
#define Enofid "fid not found"
#define Enofile "file not found"
#define Enomode "mode not supported"
#define Enofunc "function not supported"
#define Enocommand "command not supported"
char *wmii_ixp_version(IXPConn *c, Fcall *fcall);
char *wmii_ixp_attach(IXPConn *c, Fcall *fcall);
char *wmii_ixp_clunk(IXPConn *c, Fcall *fcall);
/* spawn.c */
void wmii_spawn(void *dpy, char *cmd);
/* wm.c */
int wmii_property(Display * dpy, Window w, Atom a, Atom t, long l, unsigned char **prop);
void wmii_send_message(Display * dpy, Window w, Atom a, long value);
void wmii_init_lock_modifiers(Display * dpy, unsigned int *valid_mask,
unsigned int *num_lock_mask);
extern Qid root_qid;

88
rc/keys
View File

@ -1,88 +0,0 @@
#!9PREFIX/bin/rc
# configure wmiikeys
fn xwrite { echo -n $2 | wmiir write $1 }
xwrite /keys/ctl quit >/dev/null >[2=1]
xwrite /ctl 'mount unix!/tmp/.ixp-'^$USER^'/wmiikeys-'^$WMII_IDENT^' /keys'
wmiikeys -a unix!/tmp/.ixp-$USER/wmiikeys-$WMII_IDENT &
sleep 1
wmiir -a unix!/tmp/.ixp-$USER/wmiikeys-$WMII_IDENT write /grab <<END
Control-Alt-k
Control-Alt-c
Control-Alt-q,y
Control-Alt-w,y
Alt-t
Alt-d
Alt-a
Shift-Alt-a
Alt-n
Alt-m
Alt-Return
Shift-Alt-Return
Control-Alt-y
Alt-h
Alt-l
Alt-Tab
Alt-j
Alt-k
Shift-Alt-h
Shift-Alt-l
Shift-Alt-p
Shift-Alt-1
Shift-Alt-2
Shift-Alt-3
Shift-Alt-4
END
wmiir -a unix!/tmp/.ixp-$USER/wmiikeys-$WMII_IDENT read /event | \
while(key=`{read}) {
xwrite /bar/2/data $key
switch($key) {
case Control-Alt-k
keys
case Control-Alt-c
xwrite /wm/sel/sel/sel/ctl kill
case Control-Alt-q,y
quit
case Control-Alt-w,y
wmiirc
case Alt-t
extern xterm -rv &
case Alt-d
xwrite /wm/sel/sel/sel/ctl detach
case Alt-a
xwrite /wm/ctl attach
case Shift-Alt-a
xwrite /wm/ctl detached
case Alt-n
wmiir read /wm/sel/new >/dev/null >[2=1]
case Alt-m
xwrite /wm/sel/sel/sel/ctl max
case Alt-Return
xwrite /wm/sel/sel/ctl 'swap east'
case Shift-Alt-Return
xwrite /wm/sel/sel/ctl 'swap west'
case Control-Alt-y
wmiir read /wm/new >/dev/null >[2=1]
case Alt-h
xwrite /wm/sel/ctl 'select next'
case Alt-l
xwrite /wm/sel/ctl 'select prev'
case Alt-Tab
xwrite /wm/sel/sel/ctl 'select next'
case Alt-j
xwrite /wm/sel/sel/ctl 'select next'
case Alt-k
xwrite /wm/sel/sel/ctl 'select prev'
case Shift-Alt-h
xwrite /wm/ctl 'select prev'
case Shift-Alt-l
xwrite /wm/ctl 'select next'
case Shift-Alt-p
xwrite /wm/ctl pager
case Shift-Alt-[1-9]
xwrite /wm/ctl 'select '^`{echo $k|sed 's/.*-//g'}
}
}

View File

@ -1,7 +0,0 @@
#!9PREFIX/bin/rc
# activate shortcuts of the given mode
wmiir write /keys/grabkeyb 0
wmiir write /keys/lookup /mode/$1
eval `{wmiir read /wm/event/pageupdate}

View File

@ -1,8 +0,0 @@
#!9PREFIX/bin/rc
# quit wmii
echo -n quit | wmiir write /bar/ctl
#echo -n quit | wmiir write /menu/ctl
echo -n quit | wmiir write /keys/ctl
echo -n quit | wmiir write /wm/ctl
echo -n quit | wmiir write /ctl