commit f53b8d61ef0065d23509b47e6671aefa2eec40ad
parent 1f3ecb5a7c2289fbf17de5a7665088ea9401696d
Author: garbeam <garbeam@mmv.wmii.de>
Date: Mon, 12 Dec 2005 16:08:16 +0200
renamed all wmi* prefixed tools into wmii* prefixed ones to prevent further confusion
Diffstat:
| Makefile | | | 8 | ++++---- |
| cmd/Makefile | | | 44 | ++++++++++++++++++++++---------------------- |
| cmd/wm/wmii | | | 18 | +++++++++--------- |
| cmd/wmibar.1 | | | 43 | ------------------------------------------- |
| cmd/wmibar.c | | | 534 | ------------------------------------------------------------------------------- |
| cmd/wmibar2.c | | | 449 | ------------------------------------------------------------------------------- |
| cmd/wmifs.1 | | | 38 | -------------------------------------- |
| cmd/wmifs.c | | | 376 | ------------------------------------------------------------------------------- |
| cmd/wmiibar.1 | | | 43 | +++++++++++++++++++++++++++++++++++++++++++ |
| cmd/wmiibar.c | | | 534 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| cmd/wmiibar2.c | | | 449 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| cmd/wmiifs.1 | | | 38 | ++++++++++++++++++++++++++++++++++++++ |
| cmd/wmiifs.c | | | 376 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| cmd/wmiikeys.1 | | | 45 | +++++++++++++++++++++++++++++++++++++++++++++ |
| cmd/wmiikeys.c | | | 481 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| cmd/wmiimenu.1 | | | 42 | ++++++++++++++++++++++++++++++++++++++++++ |
| cmd/wmiimenu.c | | | 621 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| cmd/wmiiplumb.c | | | 92 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| cmd/wmiir.1 | | | 71 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| cmd/wmiir.c | | | 225 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| cmd/wmiir2.c | | | 243 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| cmd/wmiiwarp.c | | | 54 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| cmd/wmikeys.1 | | | 45 | --------------------------------------------- |
| cmd/wmikeys.c | | | 481 | ------------------------------------------------------------------------------- |
| cmd/wmimenu.1 | | | 42 | ------------------------------------------ |
| cmd/wmimenu.c | | | 621 | ------------------------------------------------------------------------------- |
| cmd/wmiplumb.c | | | 92 | ------------------------------------------------------------------------------- |
| cmd/wmir.1 | | | 71 | ----------------------------------------------------------------------- |
| cmd/wmir.c | | | 225 | ------------------------------------------------------------------------------- |
| cmd/wmir2.c | | | 243 | ------------------------------------------------------------------------------- |
| cmd/wmiwarp.c | | | 54 | ------------------------------------------------------ |
| rc/kmode | | | 10 | +++++----- |
| rc/quit | | | 2 | +- |
| rc/status | | | 14 | +++++++------- |
| rc/welcome | | | 4 | ++-- |
| rc/wmiirc | | | 170 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| rc/wmirc | | | 170 | ------------------------------------------------------------------------------- |
37 files changed, 3534 insertions(+), 3534 deletions(-)
diff --git a/Makefile b/Makefile
@@ -5,11 +5,11 @@ include config.mk
SUBDIRS = libcext liblitz libixp libixp2 libwmii cmd
-BIN = cmd/wm/wmii cmd/wm/wmiiwm cmd/wmibar cmd/wmifs \
- cmd/wmikeys cmd/wmimenu cmd/wmiplumb cmd/wmir cmd/wmiwarp
+BIN = cmd/wm/wmii cmd/wm/wmiiwm cmd/wmiibar cmd/wmiifs \
+ cmd/wmiikeys cmd/wmiimenu cmd/wmiiplumb cmd/wmiir cmd/wmiiwarp
-MAN1 = cmd/wm/wmii.1 cmd/wm/wmiiwm.1 cmd/wmibar.1 cmd/wmifs.1 \
- cmd/wmikeys.1 cmd/wmimenu.1 cmd/wmir.1
+MAN1 = cmd/wm/wmii.1 cmd/wm/wmiiwm.1 cmd/wmiibar.1 cmd/wmiifs.1 \
+ cmd/wmiikeys.1 cmd/wmiimenu.1 cmd/wmiir.1
all:
@echo wmii build options:
diff --git a/cmd/Makefile b/cmd/Makefile
@@ -9,78 +9,78 @@ LDFLAGS += -L../liblitz -llitz -L../libixp -lixp \
LDFLAGS2 += ${LIBS} -L../liblitz -llitz -L../libixp2 -lixp \
-L../libwmii -lwmii -L../libcext -lcext
-SRC_bar = wmibar.c
+SRC_bar = wmiibar.c
OBJ_bar = ${SRC_bar:.c=.o}
-SRC_bar2 = wmibar2.c
+SRC_bar2 = wmiibar2.c
OBJ_bar2 = ${SRC_bar2:.c=.o}
-SRC_menu = wmimenu.c
+SRC_menu = wmiimenu.c
OBJ_menu = ${SRC_menu:.c=.o}
-SRC_r2 = wmir2.c
+SRC_r2 = wmiir2.c
OBJ_r2 = ${SRC_r2:.c=.o}
-SRC_r = wmir.c
+SRC_r = wmiir.c
OBJ_r = ${SRC_r:.c=.o}
-SRC_fs = wmifs.c
+SRC_fs = wmiifs.c
OBJ_fs = ${SRC_fs:.c=.o}
-SRC_keys = wmikeys.c
+SRC_keys = wmiikeys.c
OBJ_keys = ${SRC_keys:.c=.o}
-SRC_plumb = wmiplumb.c
+SRC_plumb = wmiiplumb.c
OBJ_plumb = ${SRC_plumb:.c=.o}
-SRC_warp = wmiwarp.c
+SRC_warp = wmiiwarp.c
OBJ_warp = ${SRC_warp:.c=.o}
-all: wmibar wmibar2 wmimenu wmir wmir2 wmifs wmikeys wmiplumb wmiwarp
- @echo built wmi commands
+all: wmiibar wmiibar2 wmiimenu wmiir wmiir2 wmiifs wmiikeys wmiiplumb wmiiwarp
+ @echo built wmii commands
.c.o:
@echo CC $<
@${CC} -c ${CFLAGS} $<
-wmibar: ${OBJ_bar}
+wmiibar: ${OBJ_bar}
@echo LD $@
@${CC} -o $@ ${OBJ_bar} ${LDFLAGS}
-wmibar2: ${OBJ_bar2}
+wmiibar2: ${OBJ_bar2}
@echo LD $@
@${CC} -o $@ ${OBJ_bar2} ${LDFLAGS2}
-wmimenu: ${OBJ_menu}
+wmiimenu: ${OBJ_menu}
@echo LD $@
@${CC} -o $@ ${OBJ_menu} ${LDFLAGS}
-wmir2: ${OBJ_r2}
+wmiir2: ${OBJ_r2}
@echo LD $@
@${CC} -o $@ ${OBJ_r2} -g -static -L${LIBDIR} -L/usr/lib -lc \
-L../libixp2 -lixp -L../libcext -lcext
-wmir: ${OBJ_r}
+wmiir: ${OBJ_r}
@echo LD $@
@${CC} -o $@ ${OBJ_r} -g -static -L${LIBDIR} -L/usr/lib -lc \
-L../libixp -lixp -L../libcext -lcext
-wmifs: ${OBJ_fs}
+wmiifs: ${OBJ_fs}
@echo LD $@
@${CC} -o $@ ${OBJ_fs} ${LDFLAGS}
-wmikeys: ${OBJ_keys}
+wmiikeys: ${OBJ_keys}
@echo LD $@
@${CC} -o $@ ${OBJ_keys} ${LDFLAGS}
-wmiplumb: ${OBJ_plumb}
+wmiiplumb: ${OBJ_plumb}
@echo LD $@
@${CC} -o $@ ${OBJ_plumb} ${LDFLAGS}
-wmiwarp: ${OBJ_warp}
+wmiiwarp: ${OBJ_warp}
@echo LD $@
@${CC} -o $@ ${OBJ_warp} ${LDFLAGS}
clean:
- rm -f wmibar wmibar2 wmimenu wmir wmir2 wmikeys wmiplumb wmifs\
- wmiwarp *.o
+ rm -f wmiibar wmiibar2 wmiimenu wmiir wmiir2 wmiikeys wmiiplumb wmiifs\
+ wmiiwarp *.o
diff --git a/cmd/wm/wmii b/cmd/wm/wmii
@@ -19,17 +19,17 @@ WMIR_SOCKET=/tmp/.ixp-$USER/wmifs-$WMII_IDENT
mkdir -p /tmp/.ixp-$USER
wmiiwm -s /tmp/.ixp-$USER/wmiiwm-$WMII_IDENT &
wmiiwmpid=$apid
-wmifs -s /tmp/.ixp-$USER/wmifs-$WMII_IDENT &
-wmikeys -s /tmp/.ixp-$USER/wmikeys-$WMII_IDENT &
-wmibar -s /tmp/.ixp-$USER/wmibar-$WMII_IDENT &
-wmimenu -s /tmp/.ixp-$USER/wmimenu-$WMII_IDENT &
+wmiifs -s /tmp/.ixp-$USER/wmiifs-$WMII_IDENT &
+wmiikeys -s /tmp/.ixp-$USER/wmiikeys-$WMII_IDENT &
+wmiibar -s /tmp/.ixp-$USER/wmiibar-$WMII_IDENT &
+wmiimenu -s /tmp/.ixp-$USER/wmiimenu-$WMII_IDENT &
sleep 1
# mount ixp file systems:
-wmir write /ctl 'bind /wm /tmp/.ixp-'^$USER/wmiiwm-$WMII_IDENT
-wmir write /ctl 'bind /bar /tmp/.ixp-'^$USER/wmibar-$WMII_IDENT
-wmir write /ctl 'bind /menu /tmp/.ixp-'^$USER/wmimenu-$WMII_IDENT
-wmir write /ctl 'bind /keys /tmp/.ixp-'^$USER/wmikeys-$WMII_IDENT
+wmiir write /ctl 'bind /wm /tmp/.ixp-'^$USER/wmiiwm-$WMII_IDENT
+wmiir write /ctl 'bind /bar /tmp/.ixp-'^$USER/wmiibar-$WMII_IDENT
+wmiir write /ctl 'bind /menu /tmp/.ixp-'^$USER/wmiimenu-$WMII_IDENT
+wmiir write /ctl 'bind /keys /tmp/.ixp-'^$USER/wmiikeys-$WMII_IDENT
# display the wmii introduction if necessary:
if(mkdir $HOME/.wmii-3 >[2]/dev/null) {
@@ -37,7 +37,7 @@ if(mkdir $HOME/.wmii-3 >[2]/dev/null) {
}
# run configuration:
-wmirc &
+wmiirc &
# wait for wmiiwm's termination:
wait $wmiiwmpid
diff --git a/cmd/wmibar.1 b/cmd/wmibar.1
@@ -1,43 +0,0 @@
-.TH WMIBAR 1 wmii-3
-.SH NAME
-wmibar \- window manager improved 2 bar
-.SH SYNOPSIS
-.B wmibar
-.B \-s
-.I socketfile
-.SH DESCRIPTION
-.SS Overview
-.B wmibar
-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 wmibar
-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 wmibar
-should create.
-.TP
-.B \-v
-prints version information to stderr, then exits.
-.SS Customization
-.B wmibar
-is customized through manipulating its filesystem namespace.
-In the default setup of
-.BR wmii (1)
-the namespace of
-.B wmibar
-can be found in /bar.
-.SH SEE ALSO
-.BR wmifs (1),
-.BR wmii (1),
-.BR wmiiwm (1),
-.BR wmikeys (1),
-.BR wmimenu (1),
-.BR wmir (1)
diff --git a/cmd/wmibar.c b/cmd/wmibar.c
@@ -1,534 +0,0 @@
-/*
- * (C)opyright MMIV-MMV 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 <X11/Xatom.h>
-#include <X11/cursorfont.h>
-#include <X11/Xproto.h>
-#include <X11/Xutil.h>
-
-#include "wmii.h"
-
-/* array indexes for file pointers */
-typedef enum {
- B_CTL,
- B_NEW,
- B_EXPANDABLE,
- B_GEOMETRY,
- B_FONT,
- B_FG_COLOR,
- B_BORDER_COLOR,
- B_BG_COLOR,
- B_LAST
-} BarIndexes;
-
-typedef struct {
- File *root;
- Draw d;
-} Item;
-
-static unsigned int id = 0;
-static IXPServer *ixps = 0;
-static Display *dpy;
-static GC gc;
-static Window win;
-static XRectangle rect;
-static XRectangle brect;
-static int screen_num;
-static int displayed = 0;
-static char *sockfile = 0;
-static File *file[B_LAST];
-static Container items = {0};
-static Pixmap pmap;
-static XFontStruct *font;
-static Align align = SOUTH;
-
-static Draw zero_draw = { 0 };
-
-static void draw_bar(void *obj, char *arg);
-static void quit(void *obj, char *arg);
-static void display(void *obj, char *arg);
-static void reset(void *obj, char *arg);
-static void _destroy(void *obj, char *arg);
-static void handle_after_write(IXPServer * s, File * f);
-
-static Action acttbl[] = {
- {"quit", quit},
- {"display", display},
- {"update", draw_bar},
- {"reset", reset},
- {"destroy", _destroy},
- {0, 0}
-};
-
-static char *version[] = {
- "wmibar - window manager improved bar - " VERSION "\n"
- " (C)opyright MMIV-MMV Anselm R. Garbe\n", 0
-};
-
-static void usage()
-{
- fprintf(stderr, "%s",
- "usage: wmibar -s <socket file> [-v]\n"
- " -s socket file\n" " -v version info\n");
- exit(1);
-}
-
-/**
- * <path>/data "<txt value>"
- * <path>/fgcolor "#RRGGBBAA"
- * <path>/bgcolor "#RRGGBBAA"
- * <path>/bordercolor "#RRGGBBAA"
- * <path>/b1press "<command>"
- * <path>/b2press "<command>"
- * <path>/b3press "<command>"
- * <path>/b4press "<command>"
- * <path>/b5press "<command>"
- */
-static void create_label(char *path)
-{
- File *f;
- char buf[MAX_BUF];
- int i;
-
- snprintf(buf, MAX_BUF, "%s/data", path);
- f = ixp_create(ixps, buf);
- f->after_write = handle_after_write;
- snprintf(buf, MAX_BUF, "%s/fgcolor", path);
- wmii_create_ixpfile(ixps, buf, file[B_FG_COLOR]->content);
- snprintf(buf, MAX_BUF, "%s/bgcolor", path);
- wmii_create_ixpfile(ixps, buf, file[B_BG_COLOR]->content);
- snprintf(buf, MAX_BUF, "%s/bordercolor", path);
- wmii_create_ixpfile(ixps, buf, file[B_BORDER_COLOR]->content);
- for (i = 1; i < 6; i++) { /* 5 buttons events */
- snprintf(buf, MAX_BUF, "%s/b%dpress", path, i);
- ixp_create(ixps, buf);
- }
-}
-
-static void _destroy(void *obj, char *arg)
-{
- char buf[512];
- if (!arg)
- return;
- snprintf(buf, sizeof(buf), "/%s", arg);
- ixps->remove(ixps, buf);
- draw_bar(0, 0);
-}
-
-static void reset(void *obj, char *arg)
-{
- int i;
- char buf[512];
- for (i = 0; i < id; i++) {
- snprintf(buf, sizeof(buf), "/%d", i);
- ixps->remove(ixps, buf);
- }
- id = 0;
- draw_bar(0, 0);
-}
-
-static void quit(void *obj, char *arg)
-{
- ixps->runlevel = SHUTDOWN;
-}
-
-static void display(void *obj, char *arg)
-{
- if (!arg)
- return;
- displayed = blitz_strtonum(arg, 0, 1);
- if (displayed) {
- XMapRaised(dpy, win);
- draw_bar(0, 0);
- } else {
- XUnmapWindow(dpy, win);
- XSync(dpy, False);
- }
-}
-
-static void init_draw_label(char *path, Draw *d)
-{
- char buf[MAX_BUF];
- File *f;
-
- /* text stuff */
- snprintf(buf, MAX_BUF, "%s/data", path);
- f = ixp_walk(ixps, buf);
- d->data = f->content;
- /* style stuff */
- snprintf(buf, MAX_BUF, "%s/fgcolor", path);
- f = ixp_walk(ixps, buf);
- d->fg = blitz_loadcolor(dpy, screen_num, f->content);
- snprintf(buf, MAX_BUF, "%s/bgcolor", path);
- f = ixp_walk(ixps, buf);
- d->bg = blitz_loadcolor(dpy, screen_num, f->content);
- snprintf(buf, MAX_BUF, "%s/bordercolor", path);
- f = ixp_walk(ixps, buf);
- d->border = blitz_loadcolor(dpy, screen_num, f->content);
-}
-
-static void init_item(char *path, Item *i)
-{
- i->d = zero_draw;
- i->root = ixp_walk(ixps, path);
- i->d.gc = gc;
- i->d.drawable = pmap;
- i->d.rect = brect;
- i->d.rect.y = 0;
- init_draw_label(path, &i->d);
-}
-
-static int comp_str(const void *s1, const void *s2)
-{
- return strcmp(*(char **) s1, *(char **) s2);
-}
-
-static void draw()
-{
- Item *item;
- unsigned int i, w, xoff = 0;
- unsigned expandable = 0;
- char buf[32];
- size_t size = cext_sizeof(&items);
-
- if (!size)
- return;
-
- expandable = blitz_strtonum(file[B_EXPANDABLE]->content, 0, size);
- snprintf(buf, sizeof(buf), "/%d", expandable);
- if (!ixp_walk(ixps, buf))
- expandable = 0;
-
- w = 0;
- /* precalc */
- for (i = 0; i < size; i++)
- if (i != expandable) {
- item = cext_list_get_item(&items, i);
- item->d.rect.width = brect.height;
- if (item->d.data) {
- if (!strncmp(item->d.data, "%m:", 3))
- /* meter */
- item->d.rect.width = brect.height / 2;
- else
- item->d.rect.width += XTextWidth(font, item->d.data, strlen(item->d.data));
- }
- w += item->d.rect.width;
- }
- if (w > brect.width) {
- /* failsafe mode, give all labels same width */
- w = brect.width / size;
- for (i = 0; i < size; i++) {
- item = cext_list_get_item(&items, i);
- item->d.rect.width = w;
- }
- item->d.rect.width = brect.width - item->d.rect.x;
- }
- else {
- item = cext_list_get_item(&items, expandable);
- item->d.rect.width = brect.width - w;
- }
- for (i = 0; i < size; i++) {
- item = cext_list_get_item(&items, i);
- item->d.font = font;
- item->d.rect.x = xoff;
- xoff += item->d.rect.width;
- if (item->d.data && !strncmp(item->d.data, "%m:", 3))
- blitz_drawmeter(dpy, &item->d);
- else
- blitz_drawlabel(dpy, &item->d);
- }
- XCopyArea(dpy, pmap, win, gc, 0, 0, brect.width, brect.height, 0, 0);
- XSync(dpy, False);
-}
-
-static void draw_bar(void *obj, char *arg)
-{
- File *label = 0;
- unsigned int i = 0, n = 0;
- Item *item;
- char buf[512];
-
- if (!displayed)
- return;
- while ((item = cext_stack_get_top_item(&items))) {
- cext_detach_item(&items, item);
- free(item);
- }
- snprintf(buf, sizeof(buf), "%s", "/0");
- label = ixp_walk(ixps, buf);
- if (!label) {
- Draw d = { 0 };
- /* default stuff */
- d.gc = gc;
- d.drawable = pmap;
- d.rect.width = brect.width;
- d.rect.height = brect.height;
- d.bg = blitz_loadcolor(dpy, screen_num, file[B_BG_COLOR]->content);
- d.fg = blitz_loadcolor(dpy, screen_num, file[B_FG_COLOR]->content);
- d.border = blitz_loadcolor(dpy, screen_num, file[B_BORDER_COLOR]->content);
- blitz_drawlabelnoborder(dpy, &d);
- } else {
- File *f;
- char **paths = 0;
- /*
- * take order into account, directory names are used in
- * alphabetical order
- */
- n = 0;
- for (f = label; f; f = f->next)
- n++;
- paths = cext_emallocz(sizeof(char *) * n);
- i = 0;
- for (f = label; f; f = f->next)
- paths[i++] = f->name;
- qsort(paths, n, sizeof(char *), comp_str);
- for (i = 0; i < n; i++) {
- snprintf(buf, sizeof(buf), "/%s", paths[i]);
- item = cext_emallocz(sizeof(Item));
- init_item(buf, item);
- cext_attach_item(&items, item);
- }
- free(paths);
- draw();
- }
-}
-
-static int comp_item_root(void *file, void *item)
-{
- File *f = file;
- Item *i = item;
-
- return f == i->root;
-}
-
-static Item *get_item_for_file(File *f)
-{
- return cext_find_item(&items, f, comp_item_root);
-}
-
-static void iter_buttonpress(void *item, void *bpress)
-{
- XButtonPressedEvent *e = bpress;
- Item *i = item;
- File *p;
- char buf[MAX_BUF];
- char path[512];
-
- if (blitz_ispointinrect(e->x, e->y, &i->d.rect)) {
- path[0] = 0;
- wmii_get_ixppath(i->root, path, sizeof(path));
- snprintf(buf, MAX_BUF, "%s/b%upress", path, e->button);
- if ((p = ixp_walk(ixps, buf)))
- if (p->content)
- spawn(dpy, p->content);
- return;
- }
-}
-
-static void handle_buttonpress(XButtonPressedEvent *e)
-{
- cext_list_iterate(&items, e, iter_buttonpress);
-}
-
-static void check_event(Connection * e)
-{
- XEvent ev;
-
- while (XPending(dpy)) {
- XNextEvent(dpy, &ev);
- switch (ev.type) {
- case ButtonPress:
- handle_buttonpress(&ev.xbutton);
- break;
- case Expose:
- if (ev.xexpose.count == 0) {
- /* XRaiseWindow(dpy, win); */
- draw_bar(0, 0);
- }
- break;
- default:
- break;
- }
- }
-}
-
-static void update_geometry()
-{
- brect = rect;
- brect.height = font->ascent + font->descent + 4;
- if (align == SOUTH)
- 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_num));
- XSync(dpy, False);
-}
-
-static void handle_after_write(IXPServer * s, File * f)
-{
- int i;
- size_t len;
- Item *item;
- char buf[512];
-
- buf[0] = 0;
- if (!strncmp(f->name, "data", 5)) {
- if ((item = get_item_for_file(f->parent))) {
- wmii_get_ixppath(f->parent, buf, sizeof(buf));
- init_draw_label(buf, &item->d);
- draw();
- }
- } else if (file[B_GEOMETRY] == f) {
- if (f->content) {
- if (!strncmp(f->content, "south", 6))
- align = SOUTH;
- else if(!strncmp(f->content, "north", 6))
- align = NORTH;
- update_geometry();
- draw_bar(0, 0);
- }
- } else if (file[B_CTL] == f) {
- for (i = 0; acttbl[i].name; i++) {
- len = strlen(acttbl[i].name);
- if (!strncmp(acttbl[i].name, (char *) f->content, len)) {
- if (strlen(f->content) > len) {
- acttbl[i].func(0, &((char *) f->content)[len + 1]);
- } else {
- acttbl[i].func(0, 0);
- }
- break;
- }
- }
- } else if (file[B_FONT] == f) {
- XFreeFont(dpy, font);
- font = blitz_getfont(dpy, file[B_FONT]->content);
- update_geometry();
- draw_bar(0, 0);
- }
- check_event(0);
-}
-
-static void handle_before_read(IXPServer * s, File * f)
-{
- char buf[64];
- if (f == file[B_GEOMETRY]) {
- if (f->content)
- free(f->content);
- if (align == SOUTH)
- f->content = strdup("south");
- else
- f->content = strdup("north");
- f->size = strlen(f->content);
- } else if (f == file[B_NEW]) {
- snprintf(buf, sizeof(buf), "%d", id++);
- if (f->content)
- free(f->content);
- f->content = strdup(buf);
- f->size = strlen(buf);
- create_label(buf);
- draw_bar(0, 0);
- }
-}
-
-static int dummy_error_handler(Display * dpy, XErrorEvent * err)
-{
- return 0;
-}
-
-int main(int argc, char *argv[])
-{
- int i;
- XSetWindowAttributes wa;
- XGCValues gcv;
-
- /* command line args */
- for (i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
- switch (argv[i][1]) {
- case 'v':
- fprintf(stdout, "%s", version[0]);
- exit(0);
- break;
- case 's':
- if (i + 1 < argc)
- sockfile = argv[++i];
- else
- usage();
- break;
- default:
- usage();
- break;
- }
- }
-
- dpy = XOpenDisplay(0);
- if (!dpy) {
- fprintf(stderr, "%s", "wmibar: cannot open display\n");
- exit(1);
- }
- XSetErrorHandler(dummy_error_handler);
- screen_num = DefaultScreen(dpy);
-
- ixps = wmii_setup_server(sockfile);
-
-
- /* init */
- if (!(file[B_CTL] = ixp_create(ixps, "/ctl"))) {
- perror("wmibar: cannot connect IXP server");
- exit(1);
- }
- file[B_CTL]->after_write = handle_after_write;
- file[B_NEW] = ixp_create(ixps, "/new");
- file[B_NEW]->before_read = handle_before_read;
- file[B_FONT] = wmii_create_ixpfile(ixps, "/font", BLITZ_FONT);
- file[B_FONT]->after_write = handle_after_write;
- font = blitz_getfont(dpy, file[B_FONT]->content);
- file[B_BG_COLOR] = wmii_create_ixpfile(ixps, "/bgcolor", BLITZ_NORM_BG_COLOR);
- file[B_FG_COLOR] = wmii_create_ixpfile(ixps, "/fgcolor", BLITZ_NORM_FG_COLOR);
- file[B_BORDER_COLOR] = wmii_create_ixpfile(ixps, "/bordercolor", BLITZ_NORM_BORDER_COLOR);
- file[B_GEOMETRY] = ixp_create(ixps, "/geometry");
- file[B_GEOMETRY]->before_read = handle_before_read;
- file[B_GEOMETRY]->after_write = handle_after_write;
- file[B_EXPANDABLE] = ixp_create(ixps, "/expandable");
-
- 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_num);
- rect.height = DisplayHeight(dpy, screen_num);
- brect = rect;
- brect.height = font->ascent + font->descent + 4;
- brect.y = rect.height - brect.height;
-
- win = XCreateWindow(dpy, RootWindow(dpy, screen_num), brect.x, brect.y,
- brect.width, brect.height, 0, DefaultDepth(dpy, screen_num),
- CopyFromParent, DefaultVisual(dpy, screen_num),
- CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
- XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_left_ptr));
- XSync(dpy, False);
-
- gcv.function = GXcopy;
- gcv.graphics_exposures = False;
- gc = XCreateGC(dpy, win, 0, 0);
-
- pmap = XCreatePixmap(dpy, win, brect.width, brect.height, DefaultDepth(dpy, screen_num));
-
- /* main event loop */
- run_server_with_fd_support(ixps, ConnectionNumber(dpy), check_event, 0);
- deinit_server(ixps);
- XFreePixmap(dpy, pmap);
- XFreeGC(dpy, gc);
- XCloseDisplay(dpy);
-
- return 0;
-}
diff --git a/cmd/wmibar2.c b/cmd/wmibar2.c
@@ -1,449 +0,0 @@
-/*
- * (C)opyright MMIV-MMV 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 "../libixp2/ixp.h"
-#include "blitz.h"
-
-/*
- * filesystem specification
- * / Droot
- * /display Fdisplay 'top', 'bottom', 'none'
- * /font Ffont <xlib font name>
- * /new Fnew returns id of new item
- * /default/ Ditem
- * /default/bNpress Fevent <command, gets executed>
- * /default/bgcolor Fcolor <#RRGGBB, #RGB>
- * /default/fgcolor Fcolor <#RRGGBB, #RGB>
- * /default/bordercolor Fcolor <#RRGGBB, #RGB>
- * /1/ Ditem
- * /1/data Fdata <arbitrary data which gets displayed>
- * /1/bNpress Fevent <command, gets executed>
- * /1/bgcolor Fcolor <#RRGGBB, #RGB>
- * /1/fgcolor Fcolor <#RRGGBB, #RGB>
- * /1/bordercolor Fcolor <#RRGGBB, #RGB> ...
- */
-enum { /* 8-bit qid.path.type */
- Droot,
- Ditem,
- Fdisplay,
- Fnew,
- Fdata, /* data to display */
- Fevent,
- Fcolor,
- Ffont
-};
-
-#define NONE (u16)0xffff
-
-typedef struct {
- char *name;
- u8 type;
-} QFile;
-
-static QFile qfilelist[] = {
- {"display", Fdisplay},
- {"font", Ffont},
- {"new", Fnew},
- {"data", Fdata},
- {"bgcolor", Fcolor},
- {"fgcolor", Fcolor},
- {"bordercolor", Fcolor},
- {"b1press", Fevent},
- {"b2press", Fevent},
- {"b3press", Fevent},
- {"b4press", Fevent},
- {"b5press", Fevent},
- {0, 0},
-};
-
-typedef struct {
- u32 fid;
- Qid qid;
-} Map;
-
-typedef struct {
- int id;
- char text[256];
- int value;
- unsigned long bg;
- unsigned long fg;
- unsigned long border[4];
- XFontStruct *font;
- char event[5][256];
-} Item;
-
-static Container items = {0};
-static char *sockfile = 0;
-static pid_t mypid = 0;
-static IXPServer srv = { 0 };
-static Qid root_qid;
-static Display *dpy;
-static int screen_num;
-static char *align = 0;
-static char *font = 0;
-/*
-static GC gc;
-static Window win;
-static XRectangle geom;
-static int mapped = 0;
-static Pixmap pmap;
-
-static Draw zero_draw = { 0 };
-*/
-
-static char *version[] = {
- "wmibar - window manager improved bar - " VERSION "\n"
- " (C)opyright MMIV-MMV Anselm R. Garbe\n", 0
-};
-
-static void usage()
-{
- fprintf(stderr, "%s %d",
- "usage: wmibar -s <socket file> [-v]\n"
- " -s socket file\n" " -v version info\n",
- NONE);
- exit(1);
-}
-
-static int dummy_error_handler(Display * dpy, XErrorEvent * err)
-{
- return 0;
-}
-
-static void exit_cleanup()
-{
- if (mypid == getpid())
- unlink(sockfile);
-}
-
-static u64 make_qpath(u8 type, u16 item, u16 file)
-{
- return ((u64) file << 24) | ((u64) item << 8) | (u64) type;
-}
-
-static u8 qpath_type(u64 path)
-{
- return path & 0xff;
-}
-
-static u16 qpath_item(u64 path)
-{
- return (path >> 8) & 0xffff;
-}
-
-/*
-static u16
-qpath_file(u64 path)
-{
- return (path >> 24) & 0xffff;
-}
-*/
-
-static int comp_fid(void *fid, void *map)
-{
- return ((Map *)map)->fid == *(u32 *)fid;
-}
-
-static Map *fid_to_map(Container *maps, u32 fid)
-{
- return cext_find_item(maps, &fid, comp_fid);
-}
-
-static Bool qfile_index(char *name, u16 * index)
-{
- int i;
- for (i = 0; qfilelist[i].name; i++)
- if (!strncmp(name, qfilelist[i].name, strlen(qfilelist[i].name))) {
- *index = i;
- return True;
- }
- return False;
-}
-
-static Bool make_qid(Qid * dir, char *wname, Qid * new)
-{
- u16 idx;
- const char *errstr;
- if (dir->type != IXP_QTDIR)
- return False;
- new->version = 0;
- if (!qfile_index(wname, &idx)) {
- new->type = IXP_QTDIR;
- if (!strncmp(wname, "..", 3)) {
- *new = root_qid;
- return True;
- } else if (!strncmp(wname, "default", 8)) {
- new->path = make_qpath(Ditem, 0, NONE);
- return True;
- }
- /* check if wname is a number, otherwise file not found */
- idx = (u16) cext_strtonum(wname, 1, 0xffff, &errstr);
- if (errstr || cext_sizeof(&items) < idx)
- return False;
- /* found */
- new->path = make_qpath(Ditem, idx, NONE);
- } else {
- new->type = IXP_QTFILE;
- new->path = make_qpath(qfilelist[idx].type, qpath_item(dir->path), idx);
- }
- return True;
-}
-
-static int attach(IXPServer *s, IXPConn *c)
-{
- Container *cont = c->aux;
- Map *map = cext_emallocz(sizeof(Map));
-
- if (!cont)
- cont = c->aux = cext_emallocz(sizeof(Container));
- fprintf(stderr, "attaching %d %s %s\n", s->fcall.afid, s->fcall.uname, s->fcall.aname);
- map->qid = root_qid;
- map->fid = s->fcall.fid;
- cext_attach_item(cont, map);
- s->fcall.id = RATTACH;
- s->fcall.qid = root_qid;
- return TRUE;
-}
-
-static int walk(IXPServer * s, IXPConn * c)
-{
- u16 nwqid = 0;
- Qid qid;
- Map *map;
-
- fprintf(stderr, "%s", "walking\n");
- if (!(map = fid_to_map(c->aux, s->fcall.fid))) {
- s->errstr = "no directory associated with fid";
- return FALSE;
- }
- if (s->fcall.fid != s->fcall.newfid
- && (fid_to_map(c->aux, s->fcall.newfid))) {
- s->errstr = "fid alreay in use";
- return FALSE;
- }
- if (s->fcall.nwname) {
- qid = map->qid;
- for (nwqid = 0; (nwqid < s->fcall.nwname) && make_qid(&qid, s->fcall.wname[nwqid], &s->fcall.wqid[nwqid]); nwqid++)
- qid = s->fcall.wqid[nwqid];
- if (!nwqid) {
- s->errstr = "file not found";
- return FALSE;
- }
- }
- /*
- * following condition is required by 9P, a fid will only be valid if
- * the walk was complete
- */
- if (nwqid == s->fcall.nwname) {
- Container *cont = c->aux;
- if (s->fcall.fid == s->fcall.newfid) {
- cext_detach_item(cont, map);
- free(map);
- }
- map = cext_emallocz(sizeof(Map));
- map->qid = qid;
- map->fid = s->fcall.newfid;
- cext_attach_item(cont, map);
- }
- s->fcall.id = RWALK;
- s->fcall.nwqid = nwqid;
- return TRUE;
-}
-
-static int _open(IXPServer * s, IXPConn * c)
-{
- Map *map = fid_to_map(c->aux, s->fcall.fid);
-
- fprintf(stderr, "%s", "opening\n");
- if (!map) {
- s->errstr = "invalid fid";
- return FALSE;
- }
- if ((s->fcall.mode != IXP_OREAD) && (s->fcall.mode != IXP_OWRITE)) {
- s->errstr = "mode not supported";
- return FALSE;
- }
- s->fcall.id = ROPEN;
- s->fcall.qid = map->qid;
- s->fcall.iounit =
- s->fcall.maxmsg - (sizeof(u8) + sizeof(u16) + 2 * sizeof(u32));
- return TRUE;
-}
-
-static int _read(IXPServer * s, IXPConn * c)
-{
- Map *map = fid_to_map(c->aux, s->fcall.fid);
- Stat stat = { 0 };
- u8 *p;
-
- fprintf(stderr, "%s", "reading\n");
- if (!map) {
- s->errstr = "invalid fid";
- return FALSE;
- }
- stat.mode = 0xff;
- 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));
-
- fprintf(stderr, "%d\n", qpath_item(map->qid.path));
- switch (qpath_type(map->qid.path)) {
- default:
- case Droot:
- p = s->fcall.data;
- cext_strlcpy(stat.name, "display", sizeof(stat.name));
- stat.length = strlen(align);
- make_qid(&root_qid, "display", &stat.qid);
- stat.size = ixp_sizeof_stat(&stat);
- s->fcall.count = stat.size;
- p = ixp_enc_stat(p, &stat);
- cext_strlcpy(stat.name, "font", sizeof(stat.name));
- stat.length = strlen(font);
- make_qid(&root_qid, "font", &stat.qid);
- stat.size = ixp_sizeof_stat(&stat);;
- s->fcall.count += stat.size;
- p = ixp_enc_stat(p, &stat);
- cext_strlcpy(stat.name, "new", sizeof(stat.name));
- stat.length = 0;
- make_qid(&root_qid, "new", &stat.qid);
- stat.size = ixp_sizeof_stat(&stat);;
- s->fcall.count += stat.size;
- p = ixp_enc_stat(p, &stat);
- s->fcall.id = RREAD;
- fprintf(stderr, "%d msize\n", s->fcall.count);
- break;
- case Ditem:
- break;
- case Fdisplay:
- break;
- case Fnew:
- break;
- case Fdata:
- break;
- case Fevent:
- break;
- case Fcolor:
- break;
- case Ffont:
- break;
- }
-
- return TRUE;
-}
-
-static int _write(IXPServer *s, IXPConn *c)
-{
-
- return FALSE;
-}
-
-static int clunk(IXPServer *s, IXPConn *c)
-{
- Container *cont = c->aux;
- Map *map = fid_to_map(cont, s->fcall.fid);
-
- if (!map) {
- s->errstr = "invalid fid";
- return FALSE;
- }
- cext_detach_item(cont, map);
- free(map);
- s->fcall.id = RCLUNK;
- return TRUE;
-}
-
-static void freeconn(IXPServer * s, IXPConn * c)
-{
- Container *cont = c->aux;
- if (cont) {
- free(cont);
- c->aux = 0;
- }
-}
-
-static IXPTFunc funcs[] = {
- {TVERSION, ixp_server_tversion},
- {TATTACH, attach},
- {TWALK, walk},
- {TOPEN, _open},
- {TREAD, _read},
- {TWRITE, _write},
- {TCLUNK, clunk},
- {0, 0}
-};
-
-int main(int argc, char *argv[])
-{
- int i;
- Item *item;
-
- /* command line args */
- for (i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
- switch (argv[i][1]) {
- case 'v':
- fprintf(stdout, "%s", version[0]);
- exit(0);
- break;
- case 's':
- if (i + 1 < argc)
- sockfile = argv[++i];
- else
- usage();
- break;
- default:
- usage();
- break;
- }
- }
-
- dpy = XOpenDisplay(0);
- if (!dpy) {
- fprintf(stderr, "%s", "wmibar: cannot open display\n");
- exit(1);
- }
- XSetErrorHandler(dummy_error_handler);
- screen_num = DefaultScreen(dpy);
-
- if (!ixp_server_init(&srv, sockfile, funcs, freeconn)) {
- fprintf(stderr, "wmibar: fatal: %s\n", srv.errstr);
- exit(1);
- }
- root_qid.type = IXP_QTDIR;
- root_qid.version = 0;
- root_qid.path = make_qpath(Droot, NONE, NONE);
-
- mypid = getpid();
- atexit(exit_cleanup);
-
- /* default item settings */
- item = cext_emallocz(sizeof(Item));
-
- align = "bottom";
- font = "fixed";
-
- ixp_server_loop(&srv);
- if (srv.errstr) {
- fprintf(stderr, "wmibar: fatal: %s\n", srv.errstr);
- ixp_server_deinit(&srv);
- exit(1);
- }
- ixp_server_deinit(&srv);
- return 0;
-}
diff --git a/cmd/wmifs.1 b/cmd/wmifs.1
@@ -1,38 +0,0 @@
-.TH WMIFS 1 wmii-3
-.SH NAME
-wmifs \- window manager improved 2 filesystem
-.SH SYNOPSIS
-.B wmifs
-.B \-s
-.I socketfile
-.SH DESCRIPTION
-.SS Overview
-.B wmifs
-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 wmifs
-should create.
-.TP
-.B \-v
-prints version information to stderr, then exits.
-.SS Customization
-.B wmifs
-is customized through manipulating its filesystem namespace.
-In the default setup of
-.BR wmii (1)
-the namespace of
-.B wmifs
-can be found in /.
-.SH SEE ALSO
-.BR wmibar (1),
-.BR wmii (1),
-.BR wmiiwm (1),
-.BR wmikeys (1),
-.BR wmimenu (1),
-.BR wmir (1)
diff --git a/cmd/wmifs.c b/cmd/wmifs.c
@@ -1,376 +0,0 @@
-/*
- * (C)opyright MMV Anselm R. Garbe <garbeam at gmail dot com>
- * See LICENSE file for license details.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "wmii.h"
-
-/* array indexes for file pointers */
-typedef enum {
- F_CTL,
- F_LAST
-} FsIndexes;
-
-typedef struct Route Route;
-struct Route {
- File dest;
- int src;
-};
-
-typedef struct Bind Bind;
-struct Bind {
- IXPClient *client;
- Route route[MAX_CONN * MAX_OPEN_FILES];
- File *mount;
- char *prefix;
-};
-
-static Display *dpy;
-static IXPServer *ixps;
-static char *sockfile = 0;
-static File *files[F_LAST];
-static Container bindings = {0};
-
-static void quit(void *obj, char *arg);
-static void bind(void *obj, char *arg);
-static void unbind(void *obj, char *arg);
-
-static Action acttbl[] = {
- {"quit", quit},
- {"unbind", unbind},
- {"bind", bind},
- {0, 0}
-};
-
-static char *version[] = {
- "wmifs - window manager improved filesystem - " VERSION "\n"
- " (C)opyright MMV Anselm R. Garbe\n", 0
-};
-
-static void usage()
-{
- fprintf(stderr,
- "usage: wmifs -s <socket file> [-v]\n"
- " -s socket file\n" " -v version info\n");
- exit(1);
-}
-
-static void iter_unbind(void *bind, void *aux)
-{
- Bind *b = bind;
- if (b->mount) {
- b->mount->content = 0;
- ixp_remove(ixps, b->prefix);
- if (ixps->errstr)
- fprintf(stderr, "wmifs: error on unbind %s: %s\n", b->prefix, ixps->errstr);
- }
-}
-
-static void quit(void *obj, char *arg)
-{
- cext_list_iterate(&bindings, nil, iter_unbind);
- ixps->runlevel = SHUTDOWN;
-}
-
-static void do_unbind(Bind * b)
-{
- cext_detach_item(&bindings, b);
- iter_unbind(b, nil);
- /* free stuff */
- deinit_client(b->client);
- free(b->prefix);
- free(b);
-}
-
-static int comp_bindpath(void *path, void *bind)
-{
- Bind *b = bind;
- return !strncmp(b->prefix, path, strlen(b->prefix));
-}
-
-static void unbind(void *obj, char *arg)
-{
- Bind *b = cext_find_item(&bindings, arg, comp_bindpath);
-
- if (!b) {
- fprintf(stderr, "wmifs: unbind: '%s' no such path\n", arg);
- return;
- }
- do_unbind(b);
-}
-
-static void bind(void *obj, char *arg)
-{
- Bind *b = 0;
- char cmd[1024];
- char *sfile;
-
- if (!arg)
- return;
- cext_strlcpy(cmd, arg, sizeof(cmd));
- sfile = strchr(cmd, ' ');
- if (!sfile) {
- fprintf(stderr, "wmifs: bind: '%s' without socket argument, ignoring\n", arg);
- return; /* shortcut with empty argument */
- }
- *sfile = 0;
- sfile++;
- if (*sfile == 0) {
- fprintf(stderr, "wmifs: bind: '%s' without socket argument, ignoring\n", arg);
- return; /* shortcut with empty argument */
- }
- b = cext_emallocz(sizeof(Bind));
- b->client = init_ixp_client(sfile);
-
- if (!b->client) {
- fprintf(stderr, "wmifs: bind: cannot connect to server '%s', ignoring\n", sfile);
- free(b);
- return;
- }
- b->prefix = strdup(cmd);
- b->mount = ixp_create(ixps, b->prefix);
- b->mount->content = b->mount; /* shall be a directory */
-
- cext_attach_item(&bindings, b);
-}
-
-static void handle_after_write(IXPServer * s, File * f)
-{
- int i;
- size_t len;
-
- for (i = 0; acttbl[i].name; i++) {
- len = strlen(acttbl[i].name);
- if (!strncmp(acttbl[i].name, (char *) f->content, len)) {
- if (strlen(f->content) > len) {
- acttbl[i].func(0, &((char *) f->content)[len + 1]);
- } else {
- acttbl[i].func(0, 0);
- }
- break;
- }
- }
-}
-
-static Bind *fd_to_bind(int fd, int *client_fd)
-{
- File *f = fd_to_file(ixps, fd);
- unsigned int i, j;
- Bind *b;
- size_t size = cext_sizeof(&bindings);
-
- if (!f)
- return nil;
- for (i = 0; i < size; i++) {
- b = cext_list_get_item(&bindings, i);
- for (j = 0; j < MAX_CONN * MAX_OPEN_FILES; j++) {
- if (&b->route[j].dest == f) {
- *client_fd = b->route[j].src;
- return b;
- }
- }
- }
- return nil;
-}
-
-static File *fixp_create(IXPServer * s, char *path)
-{
- Bind *b = cext_find_item(&bindings, path, comp_bindpath);
- size_t len;
-
- if (!b) {
- File *f = ixp_create(s, path);
- return f;
- }
- /* route to b */
- len = strlen(b->prefix);
- b->client->create(b->client, path[len] == 0 ? "/" : &path[len]);
- if (b->client->errstr) {
- if (!strcmp(b->client->errstr, DEAD_SERVER))
- do_unbind(b);
- }
- return nil;
-}
-
-static File *fixp_open(IXPServer * s, char *path)
-{
- Bind *b = cext_find_item(&bindings, path, comp_bindpath);
- int fd;
- size_t len;
-
- if (!b) {
- File *f = ixp_open(s, path);
- return f;
- }
- /* route to b */
- len = strlen(b->prefix);
- fd = b->client->open(b->client, path[len] == 0 ? "/" : &path[len]);
- if (b->client->errstr) {
- set_error(s, b->client->errstr);
- if (!strcmp(b->client->errstr, DEAD_SERVER))
- do_unbind(b);
- return nil;
- }
- b->route[fd].src = fd;
- return &b->route[fd].dest;
-}
-
-static size_t
-fixp_read(IXPServer * s, int fd, size_t offset, void *out_buf,
- size_t out_buf_len)
-{
- int cfd;
- Bind *b = fd_to_bind(fd, &cfd);
- size_t result;
-
- if (!b) {
- result = ixp_read(s, fd, offset, out_buf, out_buf_len);
- return result;
- }
- /* route to b */
- result = seek_read(b->client, cfd, offset, out_buf, out_buf_len);
- if (b->client->errstr) {
- set_error(s, b->client->errstr);
- if (!strcmp(b->client->errstr, DEAD_SERVER))
- do_unbind(b);
- }
- return result;
-}
-
-static void
-fixp_write(IXPServer * s, int fd, size_t offset, void *content,
- size_t in_len)
-{
- int cfd;
- Bind *b = fd_to_bind(fd, &cfd);
-
- if (!b) {
- ixp_write(s, fd, offset, content, in_len);
- return;
- }
- /* route to b */
- seek_write(b->client, cfd, offset, content, in_len);
- if (b->client->errstr) {
- set_error(s, b->client->errstr);
- if (!strcmp(b->client->errstr, DEAD_SERVER))
- do_unbind(b);
- }
-}
-
-static void fixp_close(IXPServer * s, int fd)
-{
- int cfd;
- Bind *b = fd_to_bind(fd, &cfd);
-
- if (!b) {
- ixp_close(s, fd);
- return;
- }
- /* route to b */
- b->client->close(b->client, cfd);
- if (b->client->errstr) {
- set_error(s, b->client->errstr);
- if (!strcmp(b->client->errstr, DEAD_SERVER))
- do_unbind(b);
- }
-}
-
-static void fixp_remove(IXPServer * s, char *path)
-{
- Bind *b = cext_find_item(&bindings, path, comp_bindpath);
- size_t len;
-
- if (!b) {
- ixp_remove(s, path);
- return;
- }
- /* route to b */
- len = strlen(b->prefix);
- b->client->remove(b->client, path[len] == 0 ? "/" : &path[len]);
- if (b->client->errstr) {
- set_error(s, b->client->errstr);
- if (!strcmp(b->client->errstr, DEAD_SERVER))
- do_unbind(b);
- }
-}
-
-static void check_event(Connection * e)
-{
- XEvent ev;
- while (XPending(dpy)) {
- /*
- * wmifs isn't interested in any X events, so just drop them
- * all
- */
- XNextEvent(dpy, &ev);
- }
- /* why check them? because X won't kill wmifs when X dies */
-}
-
-static void run()
-{
- if (!(files[F_CTL] = ixp_create(ixps, "/ctl"))) {
- perror("wmifs: cannot connect IXP server");
- exit(1);
- }
- files[F_CTL]->after_write = handle_after_write;
-
- /* routing functions */
- ixps->create = fixp_create;
- ixps->remove = fixp_remove;
- ixps->open = fixp_open;
- ixps->close = fixp_close;
- ixps->read = fixp_read;
- ixps->write = fixp_write;
-
- /* main event loop */
- run_server_with_fd_support(ixps, ConnectionNumber(dpy),
- check_event, 0);
-
- deinit_server(ixps);
-}
-
-int main(int argc, char *argv[])
-{
- int i;
-
- /* command line args */
- for (i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
- switch (argv[i][1]) {
- case 'v':
- fprintf(stdout, "%s", version[0]);
- exit(0);
- break;
- case 's':
- if (i + 1 < argc)
- sockfile = argv[++i];
- else
- usage();
- break;
- default:
- usage();
- break;
- }
- }
-
- if (!getenv("HOME")) {
- fprintf(stderr, "%s",
- "wmifs: $HOME environment variable is not set\n");
- usage();
- }
- /* just for the case X crashes/gets quit */
- dpy = XOpenDisplay(0);
- if (!dpy) {
- fprintf(stderr, "%s", "wmifs: cannot open display\n");
- exit(1);
- }
- ixps = wmii_setup_server(sockfile);
-
- run();
-
- return 0;
-}
diff --git a/cmd/wmiibar.1 b/cmd/wmiibar.1
@@ -0,0 +1,43 @@
+.TH WMIBAR 1 wmii-3
+.SH NAME
+wmibar \- window manager improved 2 bar
+.SH SYNOPSIS
+.B wmibar
+.B \-s
+.I socketfile
+.SH DESCRIPTION
+.SS Overview
+.B wmibar
+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 wmibar
+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 wmibar
+should create.
+.TP
+.B \-v
+prints version information to stderr, then exits.
+.SS Customization
+.B wmibar
+is customized through manipulating its filesystem namespace.
+In the default setup of
+.BR wmii (1)
+the namespace of
+.B wmibar
+can be found in /bar.
+.SH SEE ALSO
+.BR wmifs (1),
+.BR wmii (1),
+.BR wmiiwm (1),
+.BR wmikeys (1),
+.BR wmimenu (1),
+.BR wmir (1)
diff --git a/cmd/wmiibar.c b/cmd/wmiibar.c
@@ -0,0 +1,534 @@
+/*
+ * (C)opyright MMIV-MMV 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 <X11/Xatom.h>
+#include <X11/cursorfont.h>
+#include <X11/Xproto.h>
+#include <X11/Xutil.h>
+
+#include "wmii.h"
+
+/* array indexes for file pointers */
+typedef enum {
+ B_CTL,
+ B_NEW,
+ B_EXPANDABLE,
+ B_GEOMETRY,
+ B_FONT,
+ B_FG_COLOR,
+ B_BORDER_COLOR,
+ B_BG_COLOR,
+ B_LAST
+} BarIndexes;
+
+typedef struct {
+ File *root;
+ Draw d;
+} Item;
+
+static unsigned int id = 0;
+static IXPServer *ixps = 0;
+static Display *dpy;
+static GC gc;
+static Window win;
+static XRectangle rect;
+static XRectangle brect;
+static int screen_num;
+static int displayed = 0;
+static char *sockfile = 0;
+static File *file[B_LAST];
+static Container items = {0};
+static Pixmap pmap;
+static XFontStruct *font;
+static Align align = SOUTH;
+
+static Draw zero_draw = { 0 };
+
+static void draw_bar(void *obj, char *arg);
+static void quit(void *obj, char *arg);
+static void display(void *obj, char *arg);
+static void reset(void *obj, char *arg);
+static void _destroy(void *obj, char *arg);
+static void handle_after_write(IXPServer * s, File * f);
+
+static Action acttbl[] = {
+ {"quit", quit},
+ {"display", display},
+ {"update", draw_bar},
+ {"reset", reset},
+ {"destroy", _destroy},
+ {0, 0}
+};
+
+static char *version[] = {
+ "wmibar - window manager improved bar - " VERSION "\n"
+ " (C)opyright MMIV-MMV Anselm R. Garbe\n", 0
+};
+
+static void usage()
+{
+ fprintf(stderr, "%s",
+ "usage: wmibar -s <socket file> [-v]\n"
+ " -s socket file\n" " -v version info\n");
+ exit(1);
+}
+
+/**
+ * <path>/data "<txt value>"
+ * <path>/fgcolor "#RRGGBBAA"
+ * <path>/bgcolor "#RRGGBBAA"
+ * <path>/bordercolor "#RRGGBBAA"
+ * <path>/b1press "<command>"
+ * <path>/b2press "<command>"
+ * <path>/b3press "<command>"
+ * <path>/b4press "<command>"
+ * <path>/b5press "<command>"
+ */
+static void create_label(char *path)
+{
+ File *f;
+ char buf[MAX_BUF];
+ int i;
+
+ snprintf(buf, MAX_BUF, "%s/data", path);
+ f = ixp_create(ixps, buf);
+ f->after_write = handle_after_write;
+ snprintf(buf, MAX_BUF, "%s/fgcolor", path);
+ wmii_create_ixpfile(ixps, buf, file[B_FG_COLOR]->content);
+ snprintf(buf, MAX_BUF, "%s/bgcolor", path);
+ wmii_create_ixpfile(ixps, buf, file[B_BG_COLOR]->content);
+ snprintf(buf, MAX_BUF, "%s/bordercolor", path);
+ wmii_create_ixpfile(ixps, buf, file[B_BORDER_COLOR]->content);
+ for (i = 1; i < 6; i++) { /* 5 buttons events */
+ snprintf(buf, MAX_BUF, "%s/b%dpress", path, i);
+ ixp_create(ixps, buf);
+ }
+}
+
+static void _destroy(void *obj, char *arg)
+{
+ char buf[512];
+ if (!arg)
+ return;
+ snprintf(buf, sizeof(buf), "/%s", arg);
+ ixps->remove(ixps, buf);
+ draw_bar(0, 0);
+}
+
+static void reset(void *obj, char *arg)
+{
+ int i;
+ char buf[512];
+ for (i = 0; i < id; i++) {
+ snprintf(buf, sizeof(buf), "/%d", i);
+ ixps->remove(ixps, buf);
+ }
+ id = 0;
+ draw_bar(0, 0);
+}
+
+static void quit(void *obj, char *arg)
+{
+ ixps->runlevel = SHUTDOWN;
+}
+
+static void display(void *obj, char *arg)
+{
+ if (!arg)
+ return;
+ displayed = blitz_strtonum(arg, 0, 1);
+ if (displayed) {
+ XMapRaised(dpy, win);
+ draw_bar(0, 0);
+ } else {
+ XUnmapWindow(dpy, win);
+ XSync(dpy, False);
+ }
+}
+
+static void init_draw_label(char *path, Draw *d)
+{
+ char buf[MAX_BUF];
+ File *f;
+
+ /* text stuff */
+ snprintf(buf, MAX_BUF, "%s/data", path);
+ f = ixp_walk(ixps, buf);
+ d->data = f->content;
+ /* style stuff */
+ snprintf(buf, MAX_BUF, "%s/fgcolor", path);
+ f = ixp_walk(ixps, buf);
+ d->fg = blitz_loadcolor(dpy, screen_num, f->content);
+ snprintf(buf, MAX_BUF, "%s/bgcolor", path);
+ f = ixp_walk(ixps, buf);
+ d->bg = blitz_loadcolor(dpy, screen_num, f->content);
+ snprintf(buf, MAX_BUF, "%s/bordercolor", path);
+ f = ixp_walk(ixps, buf);
+ d->border = blitz_loadcolor(dpy, screen_num, f->content);
+}
+
+static void init_item(char *path, Item *i)
+{
+ i->d = zero_draw;
+ i->root = ixp_walk(ixps, path);
+ i->d.gc = gc;
+ i->d.drawable = pmap;
+ i->d.rect = brect;
+ i->d.rect.y = 0;
+ init_draw_label(path, &i->d);
+}
+
+static int comp_str(const void *s1, const void *s2)
+{
+ return strcmp(*(char **) s1, *(char **) s2);
+}
+
+static void draw()
+{
+ Item *item;
+ unsigned int i, w, xoff = 0;
+ unsigned expandable = 0;
+ char buf[32];
+ size_t size = cext_sizeof(&items);
+
+ if (!size)
+ return;
+
+ expandable = blitz_strtonum(file[B_EXPANDABLE]->content, 0, size);
+ snprintf(buf, sizeof(buf), "/%d", expandable);
+ if (!ixp_walk(ixps, buf))
+ expandable = 0;
+
+ w = 0;
+ /* precalc */
+ for (i = 0; i < size; i++)
+ if (i != expandable) {
+ item = cext_list_get_item(&items, i);
+ item->d.rect.width = brect.height;
+ if (item->d.data) {
+ if (!strncmp(item->d.data, "%m:", 3))
+ /* meter */
+ item->d.rect.width = brect.height / 2;
+ else
+ item->d.rect.width += XTextWidth(font, item->d.data, strlen(item->d.data));
+ }
+ w += item->d.rect.width;
+ }
+ if (w > brect.width) {
+ /* failsafe mode, give all labels same width */
+ w = brect.width / size;
+ for (i = 0; i < size; i++) {
+ item = cext_list_get_item(&items, i);
+ item->d.rect.width = w;
+ }
+ item->d.rect.width = brect.width - item->d.rect.x;
+ }
+ else {
+ item = cext_list_get_item(&items, expandable);
+ item->d.rect.width = brect.width - w;
+ }
+ for (i = 0; i < size; i++) {
+ item = cext_list_get_item(&items, i);
+ item->d.font = font;
+ item->d.rect.x = xoff;
+ xoff += item->d.rect.width;
+ if (item->d.data && !strncmp(item->d.data, "%m:", 3))
+ blitz_drawmeter(dpy, &item->d);
+ else
+ blitz_drawlabel(dpy, &item->d);
+ }
+ XCopyArea(dpy, pmap, win, gc, 0, 0, brect.width, brect.height, 0, 0);
+ XSync(dpy, False);
+}
+
+static void draw_bar(void *obj, char *arg)
+{
+ File *label = 0;
+ unsigned int i = 0, n = 0;
+ Item *item;
+ char buf[512];
+
+ if (!displayed)
+ return;
+ while ((item = cext_stack_get_top_item(&items))) {
+ cext_detach_item(&items, item);
+ free(item);
+ }
+ snprintf(buf, sizeof(buf), "%s", "/0");
+ label = ixp_walk(ixps, buf);
+ if (!label) {
+ Draw d = { 0 };
+ /* default stuff */
+ d.gc = gc;
+ d.drawable = pmap;
+ d.rect.width = brect.width;
+ d.rect.height = brect.height;
+ d.bg = blitz_loadcolor(dpy, screen_num, file[B_BG_COLOR]->content);
+ d.fg = blitz_loadcolor(dpy, screen_num, file[B_FG_COLOR]->content);
+ d.border = blitz_loadcolor(dpy, screen_num, file[B_BORDER_COLOR]->content);
+ blitz_drawlabelnoborder(dpy, &d);
+ } else {
+ File *f;
+ char **paths = 0;
+ /*
+ * take order into account, directory names are used in
+ * alphabetical order
+ */
+ n = 0;
+ for (f = label; f; f = f->next)
+ n++;
+ paths = cext_emallocz(sizeof(char *) * n);
+ i = 0;
+ for (f = label; f; f = f->next)
+ paths[i++] = f->name;
+ qsort(paths, n, sizeof(char *), comp_str);
+ for (i = 0; i < n; i++) {
+ snprintf(buf, sizeof(buf), "/%s", paths[i]);
+ item = cext_emallocz(sizeof(Item));
+ init_item(buf, item);
+ cext_attach_item(&items, item);
+ }
+ free(paths);
+ draw();
+ }
+}
+
+static int comp_item_root(void *file, void *item)
+{
+ File *f = file;
+ Item *i = item;
+
+ return f == i->root;
+}
+
+static Item *get_item_for_file(File *f)
+{
+ return cext_find_item(&items, f, comp_item_root);
+}
+
+static void iter_buttonpress(void *item, void *bpress)
+{
+ XButtonPressedEvent *e = bpress;
+ Item *i = item;
+ File *p;
+ char buf[MAX_BUF];
+ char path[512];
+
+ if (blitz_ispointinrect(e->x, e->y, &i->d.rect)) {
+ path[0] = 0;
+ wmii_get_ixppath(i->root, path, sizeof(path));
+ snprintf(buf, MAX_BUF, "%s/b%upress", path, e->button);
+ if ((p = ixp_walk(ixps, buf)))
+ if (p->content)
+ spawn(dpy, p->content);
+ return;
+ }
+}
+
+static void handle_buttonpress(XButtonPressedEvent *e)
+{
+ cext_list_iterate(&items, e, iter_buttonpress);
+}
+
+static void check_event(Connection * e)
+{
+ XEvent ev;
+
+ while (XPending(dpy)) {
+ XNextEvent(dpy, &ev);
+ switch (ev.type) {
+ case ButtonPress:
+ handle_buttonpress(&ev.xbutton);
+ break;
+ case Expose:
+ if (ev.xexpose.count == 0) {
+ /* XRaiseWindow(dpy, win); */
+ draw_bar(0, 0);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void update_geometry()
+{
+ brect = rect;
+ brect.height = font->ascent + font->descent + 4;
+ if (align == SOUTH)
+ 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_num));
+ XSync(dpy, False);
+}
+
+static void handle_after_write(IXPServer * s, File * f)
+{
+ int i;
+ size_t len;
+ Item *item;
+ char buf[512];
+
+ buf[0] = 0;
+ if (!strncmp(f->name, "data", 5)) {
+ if ((item = get_item_for_file(f->parent))) {
+ wmii_get_ixppath(f->parent, buf, sizeof(buf));
+ init_draw_label(buf, &item->d);
+ draw();
+ }
+ } else if (file[B_GEOMETRY] == f) {
+ if (f->content) {
+ if (!strncmp(f->content, "south", 6))
+ align = SOUTH;
+ else if(!strncmp(f->content, "north", 6))
+ align = NORTH;
+ update_geometry();
+ draw_bar(0, 0);
+ }
+ } else if (file[B_CTL] == f) {
+ for (i = 0; acttbl[i].name; i++) {
+ len = strlen(acttbl[i].name);
+ if (!strncmp(acttbl[i].name, (char *) f->content, len)) {
+ if (strlen(f->content) > len) {
+ acttbl[i].func(0, &((char *) f->content)[len + 1]);
+ } else {
+ acttbl[i].func(0, 0);
+ }
+ break;
+ }
+ }
+ } else if (file[B_FONT] == f) {
+ XFreeFont(dpy, font);
+ font = blitz_getfont(dpy, file[B_FONT]->content);
+ update_geometry();
+ draw_bar(0, 0);
+ }
+ check_event(0);
+}
+
+static void handle_before_read(IXPServer * s, File * f)
+{
+ char buf[64];
+ if (f == file[B_GEOMETRY]) {
+ if (f->content)
+ free(f->content);
+ if (align == SOUTH)
+ f->content = strdup("south");
+ else
+ f->content = strdup("north");
+ f->size = strlen(f->content);
+ } else if (f == file[B_NEW]) {
+ snprintf(buf, sizeof(buf), "%d", id++);
+ if (f->content)
+ free(f->content);
+ f->content = strdup(buf);
+ f->size = strlen(buf);
+ create_label(buf);
+ draw_bar(0, 0);
+ }
+}
+
+static int dummy_error_handler(Display * dpy, XErrorEvent * err)
+{
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+ XSetWindowAttributes wa;
+ XGCValues gcv;
+
+ /* command line args */
+ for (i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
+ switch (argv[i][1]) {
+ case 'v':
+ fprintf(stdout, "%s", version[0]);
+ exit(0);
+ break;
+ case 's':
+ if (i + 1 < argc)
+ sockfile = argv[++i];
+ else
+ usage();
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ dpy = XOpenDisplay(0);
+ if (!dpy) {
+ fprintf(stderr, "%s", "wmibar: cannot open display\n");
+ exit(1);
+ }
+ XSetErrorHandler(dummy_error_handler);
+ screen_num = DefaultScreen(dpy);
+
+ ixps = wmii_setup_server(sockfile);
+
+
+ /* init */
+ if (!(file[B_CTL] = ixp_create(ixps, "/ctl"))) {
+ perror("wmibar: cannot connect IXP server");
+ exit(1);
+ }
+ file[B_CTL]->after_write = handle_after_write;
+ file[B_NEW] = ixp_create(ixps, "/new");
+ file[B_NEW]->before_read = handle_before_read;
+ file[B_FONT] = wmii_create_ixpfile(ixps, "/font", BLITZ_FONT);
+ file[B_FONT]->after_write = handle_after_write;
+ font = blitz_getfont(dpy, file[B_FONT]->content);
+ file[B_BG_COLOR] = wmii_create_ixpfile(ixps, "/bgcolor", BLITZ_NORM_BG_COLOR);
+ file[B_FG_COLOR] = wmii_create_ixpfile(ixps, "/fgcolor", BLITZ_NORM_FG_COLOR);
+ file[B_BORDER_COLOR] = wmii_create_ixpfile(ixps, "/bordercolor", BLITZ_NORM_BORDER_COLOR);
+ file[B_GEOMETRY] = ixp_create(ixps, "/geometry");
+ file[B_GEOMETRY]->before_read = handle_before_read;
+ file[B_GEOMETRY]->after_write = handle_after_write;
+ file[B_EXPANDABLE] = ixp_create(ixps, "/expandable");
+
+ 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_num);
+ rect.height = DisplayHeight(dpy, screen_num);
+ brect = rect;
+ brect.height = font->ascent + font->descent + 4;
+ brect.y = rect.height - brect.height;
+
+ win = XCreateWindow(dpy, RootWindow(dpy, screen_num), brect.x, brect.y,
+ brect.width, brect.height, 0, DefaultDepth(dpy, screen_num),
+ CopyFromParent, DefaultVisual(dpy, screen_num),
+ CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
+ XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_left_ptr));
+ XSync(dpy, False);
+
+ gcv.function = GXcopy;
+ gcv.graphics_exposures = False;
+ gc = XCreateGC(dpy, win, 0, 0);
+
+ pmap = XCreatePixmap(dpy, win, brect.width, brect.height, DefaultDepth(dpy, screen_num));
+
+ /* main event loop */
+ run_server_with_fd_support(ixps, ConnectionNumber(dpy), check_event, 0);
+ deinit_server(ixps);
+ XFreePixmap(dpy, pmap);
+ XFreeGC(dpy, gc);
+ XCloseDisplay(dpy);
+
+ return 0;
+}
diff --git a/cmd/wmiibar2.c b/cmd/wmiibar2.c
@@ -0,0 +1,449 @@
+/*
+ * (C)opyright MMIV-MMV 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 "../libixp2/ixp.h"
+#include "blitz.h"
+
+/*
+ * filesystem specification
+ * / Droot
+ * /display Fdisplay 'top', 'bottom', 'none'
+ * /font Ffont <xlib font name>
+ * /new Fnew returns id of new item
+ * /default/ Ditem
+ * /default/bNpress Fevent <command, gets executed>
+ * /default/bgcolor Fcolor <#RRGGBB, #RGB>
+ * /default/fgcolor Fcolor <#RRGGBB, #RGB>
+ * /default/bordercolor Fcolor <#RRGGBB, #RGB>
+ * /1/ Ditem
+ * /1/data Fdata <arbitrary data which gets displayed>
+ * /1/bNpress Fevent <command, gets executed>
+ * /1/bgcolor Fcolor <#RRGGBB, #RGB>
+ * /1/fgcolor Fcolor <#RRGGBB, #RGB>
+ * /1/bordercolor Fcolor <#RRGGBB, #RGB> ...
+ */
+enum { /* 8-bit qid.path.type */
+ Droot,
+ Ditem,
+ Fdisplay,
+ Fnew,
+ Fdata, /* data to display */
+ Fevent,
+ Fcolor,
+ Ffont
+};
+
+#define NONE (u16)0xffff
+
+typedef struct {
+ char *name;
+ u8 type;
+} QFile;
+
+static QFile qfilelist[] = {
+ {"display", Fdisplay},
+ {"font", Ffont},
+ {"new", Fnew},
+ {"data", Fdata},
+ {"bgcolor", Fcolor},
+ {"fgcolor", Fcolor},
+ {"bordercolor", Fcolor},
+ {"b1press", Fevent},
+ {"b2press", Fevent},
+ {"b3press", Fevent},
+ {"b4press", Fevent},
+ {"b5press", Fevent},
+ {0, 0},
+};
+
+typedef struct {
+ u32 fid;
+ Qid qid;
+} Map;
+
+typedef struct {
+ int id;
+ char text[256];
+ int value;
+ unsigned long bg;
+ unsigned long fg;
+ unsigned long border[4];
+ XFontStruct *font;
+ char event[5][256];
+} Item;
+
+static Container items = {0};
+static char *sockfile = 0;
+static pid_t mypid = 0;
+static IXPServer srv = { 0 };
+static Qid root_qid;
+static Display *dpy;
+static int screen_num;
+static char *align = 0;
+static char *font = 0;
+/*
+static GC gc;
+static Window win;
+static XRectangle geom;
+static int mapped = 0;
+static Pixmap pmap;
+
+static Draw zero_draw = { 0 };
+*/
+
+static char *version[] = {
+ "wmibar - window manager improved bar - " VERSION "\n"
+ " (C)opyright MMIV-MMV Anselm R. Garbe\n", 0
+};
+
+static void usage()
+{
+ fprintf(stderr, "%s %d",
+ "usage: wmibar -s <socket file> [-v]\n"
+ " -s socket file\n" " -v version info\n",
+ NONE);
+ exit(1);
+}
+
+static int dummy_error_handler(Display * dpy, XErrorEvent * err)
+{
+ return 0;
+}
+
+static void exit_cleanup()
+{
+ if (mypid == getpid())
+ unlink(sockfile);
+}
+
+static u64 make_qpath(u8 type, u16 item, u16 file)
+{
+ return ((u64) file << 24) | ((u64) item << 8) | (u64) type;
+}
+
+static u8 qpath_type(u64 path)
+{
+ return path & 0xff;
+}
+
+static u16 qpath_item(u64 path)
+{
+ return (path >> 8) & 0xffff;
+}
+
+/*
+static u16
+qpath_file(u64 path)
+{
+ return (path >> 24) & 0xffff;
+}
+*/
+
+static int comp_fid(void *fid, void *map)
+{
+ return ((Map *)map)->fid == *(u32 *)fid;
+}
+
+static Map *fid_to_map(Container *maps, u32 fid)
+{
+ return cext_find_item(maps, &fid, comp_fid);
+}
+
+static Bool qfile_index(char *name, u16 * index)
+{
+ int i;
+ for (i = 0; qfilelist[i].name; i++)
+ if (!strncmp(name, qfilelist[i].name, strlen(qfilelist[i].name))) {
+ *index = i;
+ return True;
+ }
+ return False;
+}
+
+static Bool make_qid(Qid * dir, char *wname, Qid * new)
+{
+ u16 idx;
+ const char *errstr;
+ if (dir->type != IXP_QTDIR)
+ return False;
+ new->version = 0;
+ if (!qfile_index(wname, &idx)) {
+ new->type = IXP_QTDIR;
+ if (!strncmp(wname, "..", 3)) {
+ *new = root_qid;
+ return True;
+ } else if (!strncmp(wname, "default", 8)) {
+ new->path = make_qpath(Ditem, 0, NONE);
+ return True;
+ }
+ /* check if wname is a number, otherwise file not found */
+ idx = (u16) cext_strtonum(wname, 1, 0xffff, &errstr);
+ if (errstr || cext_sizeof(&items) < idx)
+ return False;
+ /* found */
+ new->path = make_qpath(Ditem, idx, NONE);
+ } else {
+ new->type = IXP_QTFILE;
+ new->path = make_qpath(qfilelist[idx].type, qpath_item(dir->path), idx);
+ }
+ return True;
+}
+
+static int attach(IXPServer *s, IXPConn *c)
+{
+ Container *cont = c->aux;
+ Map *map = cext_emallocz(sizeof(Map));
+
+ if (!cont)
+ cont = c->aux = cext_emallocz(sizeof(Container));
+ fprintf(stderr, "attaching %d %s %s\n", s->fcall.afid, s->fcall.uname, s->fcall.aname);
+ map->qid = root_qid;
+ map->fid = s->fcall.fid;
+ cext_attach_item(cont, map);
+ s->fcall.id = RATTACH;
+ s->fcall.qid = root_qid;
+ return TRUE;
+}
+
+static int walk(IXPServer * s, IXPConn * c)
+{
+ u16 nwqid = 0;
+ Qid qid;
+ Map *map;
+
+ fprintf(stderr, "%s", "walking\n");
+ if (!(map = fid_to_map(c->aux, s->fcall.fid))) {
+ s->errstr = "no directory associated with fid";
+ return FALSE;
+ }
+ if (s->fcall.fid != s->fcall.newfid
+ && (fid_to_map(c->aux, s->fcall.newfid))) {
+ s->errstr = "fid alreay in use";
+ return FALSE;
+ }
+ if (s->fcall.nwname) {
+ qid = map->qid;
+ for (nwqid = 0; (nwqid < s->fcall.nwname) && make_qid(&qid, s->fcall.wname[nwqid], &s->fcall.wqid[nwqid]); nwqid++)
+ qid = s->fcall.wqid[nwqid];
+ if (!nwqid) {
+ s->errstr = "file not found";
+ return FALSE;
+ }
+ }
+ /*
+ * following condition is required by 9P, a fid will only be valid if
+ * the walk was complete
+ */
+ if (nwqid == s->fcall.nwname) {
+ Container *cont = c->aux;
+ if (s->fcall.fid == s->fcall.newfid) {
+ cext_detach_item(cont, map);
+ free(map);
+ }
+ map = cext_emallocz(sizeof(Map));
+ map->qid = qid;
+ map->fid = s->fcall.newfid;
+ cext_attach_item(cont, map);
+ }
+ s->fcall.id = RWALK;
+ s->fcall.nwqid = nwqid;
+ return TRUE;
+}
+
+static int _open(IXPServer * s, IXPConn * c)
+{
+ Map *map = fid_to_map(c->aux, s->fcall.fid);
+
+ fprintf(stderr, "%s", "opening\n");
+ if (!map) {
+ s->errstr = "invalid fid";
+ return FALSE;
+ }
+ if ((s->fcall.mode != IXP_OREAD) && (s->fcall.mode != IXP_OWRITE)) {
+ s->errstr = "mode not supported";
+ return FALSE;
+ }
+ s->fcall.id = ROPEN;
+ s->fcall.qid = map->qid;
+ s->fcall.iounit =
+ s->fcall.maxmsg - (sizeof(u8) + sizeof(u16) + 2 * sizeof(u32));
+ return TRUE;
+}
+
+static int _read(IXPServer * s, IXPConn * c)
+{
+ Map *map = fid_to_map(c->aux, s->fcall.fid);
+ Stat stat = { 0 };
+ u8 *p;
+
+ fprintf(stderr, "%s", "reading\n");
+ if (!map) {
+ s->errstr = "invalid fid";
+ return FALSE;
+ }
+ stat.mode = 0xff;
+ 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));
+
+ fprintf(stderr, "%d\n", qpath_item(map->qid.path));
+ switch (qpath_type(map->qid.path)) {
+ default:
+ case Droot:
+ p = s->fcall.data;
+ cext_strlcpy(stat.name, "display", sizeof(stat.name));
+ stat.length = strlen(align);
+ make_qid(&root_qid, "display", &stat.qid);
+ stat.size = ixp_sizeof_stat(&stat);
+ s->fcall.count = stat.size;
+ p = ixp_enc_stat(p, &stat);
+ cext_strlcpy(stat.name, "font", sizeof(stat.name));
+ stat.length = strlen(font);
+ make_qid(&root_qid, "font", &stat.qid);
+ stat.size = ixp_sizeof_stat(&stat);;
+ s->fcall.count += stat.size;
+ p = ixp_enc_stat(p, &stat);
+ cext_strlcpy(stat.name, "new", sizeof(stat.name));
+ stat.length = 0;
+ make_qid(&root_qid, "new", &stat.qid);
+ stat.size = ixp_sizeof_stat(&stat);;
+ s->fcall.count += stat.size;
+ p = ixp_enc_stat(p, &stat);
+ s->fcall.id = RREAD;
+ fprintf(stderr, "%d msize\n", s->fcall.count);
+ break;
+ case Ditem:
+ break;
+ case Fdisplay:
+ break;
+ case Fnew:
+ break;
+ case Fdata:
+ break;
+ case Fevent:
+ break;
+ case Fcolor:
+ break;
+ case Ffont:
+ break;
+ }
+
+ return TRUE;
+}
+
+static int _write(IXPServer *s, IXPConn *c)
+{
+
+ return FALSE;
+}
+
+static int clunk(IXPServer *s, IXPConn *c)
+{
+ Container *cont = c->aux;
+ Map *map = fid_to_map(cont, s->fcall.fid);
+
+ if (!map) {
+ s->errstr = "invalid fid";
+ return FALSE;
+ }
+ cext_detach_item(cont, map);
+ free(map);
+ s->fcall.id = RCLUNK;
+ return TRUE;
+}
+
+static void freeconn(IXPServer * s, IXPConn * c)
+{
+ Container *cont = c->aux;
+ if (cont) {
+ free(cont);
+ c->aux = 0;
+ }
+}
+
+static IXPTFunc funcs[] = {
+ {TVERSION, ixp_server_tversion},
+ {TATTACH, attach},
+ {TWALK, walk},
+ {TOPEN, _open},
+ {TREAD, _read},
+ {TWRITE, _write},
+ {TCLUNK, clunk},
+ {0, 0}
+};
+
+int main(int argc, char *argv[])
+{
+ int i;
+ Item *item;
+
+ /* command line args */
+ for (i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
+ switch (argv[i][1]) {
+ case 'v':
+ fprintf(stdout, "%s", version[0]);
+ exit(0);
+ break;
+ case 's':
+ if (i + 1 < argc)
+ sockfile = argv[++i];
+ else
+ usage();
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ dpy = XOpenDisplay(0);
+ if (!dpy) {
+ fprintf(stderr, "%s", "wmibar: cannot open display\n");
+ exit(1);
+ }
+ XSetErrorHandler(dummy_error_handler);
+ screen_num = DefaultScreen(dpy);
+
+ if (!ixp_server_init(&srv, sockfile, funcs, freeconn)) {
+ fprintf(stderr, "wmibar: fatal: %s\n", srv.errstr);
+ exit(1);
+ }
+ root_qid.type = IXP_QTDIR;
+ root_qid.version = 0;
+ root_qid.path = make_qpath(Droot, NONE, NONE);
+
+ mypid = getpid();
+ atexit(exit_cleanup);
+
+ /* default item settings */
+ item = cext_emallocz(sizeof(Item));
+
+ align = "bottom";
+ font = "fixed";
+
+ ixp_server_loop(&srv);
+ if (srv.errstr) {
+ fprintf(stderr, "wmibar: fatal: %s\n", srv.errstr);
+ ixp_server_deinit(&srv);
+ exit(1);
+ }
+ ixp_server_deinit(&srv);
+ return 0;
+}
diff --git a/cmd/wmiifs.1 b/cmd/wmiifs.1
@@ -0,0 +1,38 @@
+.TH WMIFS 1 wmii-3
+.SH NAME
+wmifs \- window manager improved 2 filesystem
+.SH SYNOPSIS
+.B wmifs
+.B \-s
+.I socketfile
+.SH DESCRIPTION
+.SS Overview
+.B wmifs
+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 wmifs
+should create.
+.TP
+.B \-v
+prints version information to stderr, then exits.
+.SS Customization
+.B wmifs
+is customized through manipulating its filesystem namespace.
+In the default setup of
+.BR wmii (1)
+the namespace of
+.B wmifs
+can be found in /.
+.SH SEE ALSO
+.BR wmibar (1),
+.BR wmii (1),
+.BR wmiiwm (1),
+.BR wmikeys (1),
+.BR wmimenu (1),
+.BR wmir (1)
diff --git a/cmd/wmiifs.c b/cmd/wmiifs.c
@@ -0,0 +1,376 @@
+/*
+ * (C)opyright MMV Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wmii.h"
+
+/* array indexes for file pointers */
+typedef enum {
+ F_CTL,
+ F_LAST
+} FsIndexes;
+
+typedef struct Route Route;
+struct Route {
+ File dest;
+ int src;
+};
+
+typedef struct Bind Bind;
+struct Bind {
+ IXPClient *client;
+ Route route[MAX_CONN * MAX_OPEN_FILES];
+ File *mount;
+ char *prefix;
+};
+
+static Display *dpy;
+static IXPServer *ixps;
+static char *sockfile = 0;
+static File *files[F_LAST];
+static Container bindings = {0};
+
+static void quit(void *obj, char *arg);
+static void bind(void *obj, char *arg);
+static void unbind(void *obj, char *arg);
+
+static Action acttbl[] = {
+ {"quit", quit},
+ {"unbind", unbind},
+ {"bind", bind},
+ {0, 0}
+};
+
+static char *version[] = {
+ "wmifs - window manager improved filesystem - " VERSION "\n"
+ " (C)opyright MMV Anselm R. Garbe\n", 0
+};
+
+static void usage()
+{
+ fprintf(stderr,
+ "usage: wmifs -s <socket file> [-v]\n"
+ " -s socket file\n" " -v version info\n");
+ exit(1);
+}
+
+static void iter_unbind(void *bind, void *aux)
+{
+ Bind *b = bind;
+ if (b->mount) {
+ b->mount->content = 0;
+ ixp_remove(ixps, b->prefix);
+ if (ixps->errstr)
+ fprintf(stderr, "wmifs: error on unbind %s: %s\n", b->prefix, ixps->errstr);
+ }
+}
+
+static void quit(void *obj, char *arg)
+{
+ cext_list_iterate(&bindings, nil, iter_unbind);
+ ixps->runlevel = SHUTDOWN;
+}
+
+static void do_unbind(Bind * b)
+{
+ cext_detach_item(&bindings, b);
+ iter_unbind(b, nil);
+ /* free stuff */
+ deinit_client(b->client);
+ free(b->prefix);
+ free(b);
+}
+
+static int comp_bindpath(void *path, void *bind)
+{
+ Bind *b = bind;
+ return !strncmp(b->prefix, path, strlen(b->prefix));
+}
+
+static void unbind(void *obj, char *arg)
+{
+ Bind *b = cext_find_item(&bindings, arg, comp_bindpath);
+
+ if (!b) {
+ fprintf(stderr, "wmifs: unbind: '%s' no such path\n", arg);
+ return;
+ }
+ do_unbind(b);
+}
+
+static void bind(void *obj, char *arg)
+{
+ Bind *b = 0;
+ char cmd[1024];
+ char *sfile;
+
+ if (!arg)
+ return;
+ cext_strlcpy(cmd, arg, sizeof(cmd));
+ sfile = strchr(cmd, ' ');
+ if (!sfile) {
+ fprintf(stderr, "wmifs: bind: '%s' without socket argument, ignoring\n", arg);
+ return; /* shortcut with empty argument */
+ }
+ *sfile = 0;
+ sfile++;
+ if (*sfile == 0) {
+ fprintf(stderr, "wmifs: bind: '%s' without socket argument, ignoring\n", arg);
+ return; /* shortcut with empty argument */
+ }
+ b = cext_emallocz(sizeof(Bind));
+ b->client = init_ixp_client(sfile);
+
+ if (!b->client) {
+ fprintf(stderr, "wmifs: bind: cannot connect to server '%s', ignoring\n", sfile);
+ free(b);
+ return;
+ }
+ b->prefix = strdup(cmd);
+ b->mount = ixp_create(ixps, b->prefix);
+ b->mount->content = b->mount; /* shall be a directory */
+
+ cext_attach_item(&bindings, b);
+}
+
+static void handle_after_write(IXPServer * s, File * f)
+{
+ int i;
+ size_t len;
+
+ for (i = 0; acttbl[i].name; i++) {
+ len = strlen(acttbl[i].name);
+ if (!strncmp(acttbl[i].name, (char *) f->content, len)) {
+ if (strlen(f->content) > len) {
+ acttbl[i].func(0, &((char *) f->content)[len + 1]);
+ } else {
+ acttbl[i].func(0, 0);
+ }
+ break;
+ }
+ }
+}
+
+static Bind *fd_to_bind(int fd, int *client_fd)
+{
+ File *f = fd_to_file(ixps, fd);
+ unsigned int i, j;
+ Bind *b;
+ size_t size = cext_sizeof(&bindings);
+
+ if (!f)
+ return nil;
+ for (i = 0; i < size; i++) {
+ b = cext_list_get_item(&bindings, i);
+ for (j = 0; j < MAX_CONN * MAX_OPEN_FILES; j++) {
+ if (&b->route[j].dest == f) {
+ *client_fd = b->route[j].src;
+ return b;
+ }
+ }
+ }
+ return nil;
+}
+
+static File *fixp_create(IXPServer * s, char *path)
+{
+ Bind *b = cext_find_item(&bindings, path, comp_bindpath);
+ size_t len;
+
+ if (!b) {
+ File *f = ixp_create(s, path);
+ return f;
+ }
+ /* route to b */
+ len = strlen(b->prefix);
+ b->client->create(b->client, path[len] == 0 ? "/" : &path[len]);
+ if (b->client->errstr) {
+ if (!strcmp(b->client->errstr, DEAD_SERVER))
+ do_unbind(b);
+ }
+ return nil;
+}
+
+static File *fixp_open(IXPServer * s, char *path)
+{
+ Bind *b = cext_find_item(&bindings, path, comp_bindpath);
+ int fd;
+ size_t len;
+
+ if (!b) {
+ File *f = ixp_open(s, path);
+ return f;
+ }
+ /* route to b */
+ len = strlen(b->prefix);
+ fd = b->client->open(b->client, path[len] == 0 ? "/" : &path[len]);
+ if (b->client->errstr) {
+ set_error(s, b->client->errstr);
+ if (!strcmp(b->client->errstr, DEAD_SERVER))
+ do_unbind(b);
+ return nil;
+ }
+ b->route[fd].src = fd;
+ return &b->route[fd].dest;
+}
+
+static size_t
+fixp_read(IXPServer * s, int fd, size_t offset, void *out_buf,
+ size_t out_buf_len)
+{
+ int cfd;
+ Bind *b = fd_to_bind(fd, &cfd);
+ size_t result;
+
+ if (!b) {
+ result = ixp_read(s, fd, offset, out_buf, out_buf_len);
+ return result;
+ }
+ /* route to b */
+ result = seek_read(b->client, cfd, offset, out_buf, out_buf_len);
+ if (b->client->errstr) {
+ set_error(s, b->client->errstr);
+ if (!strcmp(b->client->errstr, DEAD_SERVER))
+ do_unbind(b);
+ }
+ return result;
+}
+
+static void
+fixp_write(IXPServer * s, int fd, size_t offset, void *content,
+ size_t in_len)
+{
+ int cfd;
+ Bind *b = fd_to_bind(fd, &cfd);
+
+ if (!b) {
+ ixp_write(s, fd, offset, content, in_len);
+ return;
+ }
+ /* route to b */
+ seek_write(b->client, cfd, offset, content, in_len);
+ if (b->client->errstr) {
+ set_error(s, b->client->errstr);
+ if (!strcmp(b->client->errstr, DEAD_SERVER))
+ do_unbind(b);
+ }
+}
+
+static void fixp_close(IXPServer * s, int fd)
+{
+ int cfd;
+ Bind *b = fd_to_bind(fd, &cfd);
+
+ if (!b) {
+ ixp_close(s, fd);
+ return;
+ }
+ /* route to b */
+ b->client->close(b->client, cfd);
+ if (b->client->errstr) {
+ set_error(s, b->client->errstr);
+ if (!strcmp(b->client->errstr, DEAD_SERVER))
+ do_unbind(b);
+ }
+}
+
+static void fixp_remove(IXPServer * s, char *path)
+{
+ Bind *b = cext_find_item(&bindings, path, comp_bindpath);
+ size_t len;
+
+ if (!b) {
+ ixp_remove(s, path);
+ return;
+ }
+ /* route to b */
+ len = strlen(b->prefix);
+ b->client->remove(b->client, path[len] == 0 ? "/" : &path[len]);
+ if (b->client->errstr) {
+ set_error(s, b->client->errstr);
+ if (!strcmp(b->client->errstr, DEAD_SERVER))
+ do_unbind(b);
+ }
+}
+
+static void check_event(Connection * e)
+{
+ XEvent ev;
+ while (XPending(dpy)) {
+ /*
+ * wmifs isn't interested in any X events, so just drop them
+ * all
+ */
+ XNextEvent(dpy, &ev);
+ }
+ /* why check them? because X won't kill wmifs when X dies */
+}
+
+static void run()
+{
+ if (!(files[F_CTL] = ixp_create(ixps, "/ctl"))) {
+ perror("wmifs: cannot connect IXP server");
+ exit(1);
+ }
+ files[F_CTL]->after_write = handle_after_write;
+
+ /* routing functions */
+ ixps->create = fixp_create;
+ ixps->remove = fixp_remove;
+ ixps->open = fixp_open;
+ ixps->close = fixp_close;
+ ixps->read = fixp_read;
+ ixps->write = fixp_write;
+
+ /* main event loop */
+ run_server_with_fd_support(ixps, ConnectionNumber(dpy),
+ check_event, 0);
+
+ deinit_server(ixps);
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+
+ /* command line args */
+ for (i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
+ switch (argv[i][1]) {
+ case 'v':
+ fprintf(stdout, "%s", version[0]);
+ exit(0);
+ break;
+ case 's':
+ if (i + 1 < argc)
+ sockfile = argv[++i];
+ else
+ usage();
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ if (!getenv("HOME")) {
+ fprintf(stderr, "%s",
+ "wmifs: $HOME environment variable is not set\n");
+ usage();
+ }
+ /* just for the case X crashes/gets quit */
+ dpy = XOpenDisplay(0);
+ if (!dpy) {
+ fprintf(stderr, "%s", "wmifs: cannot open display\n");
+ exit(1);
+ }
+ ixps = wmii_setup_server(sockfile);
+
+ run();
+
+ return 0;
+}
diff --git a/cmd/wmiikeys.1 b/cmd/wmiikeys.1
@@ -0,0 +1,45 @@
+.TH WMIKEYS 1 wmii-3
+.SH NAME
+wmikeys \- window manager improved 2 keys
+.SH SYNOPSIS
+.B wmikeys
+.B \-s
+.I socketfile
+.SH DESCRIPTION
+.SS Overview
+.B wmikeys
+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 wmikeys
+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 wmikeys
+should create.
+.TP
+.B \-v
+prints version information to stderr, then exits.
+.SS Customization
+.B wmikeys
+is customized through manipulating its filesystem namespace.
+In the default setup of
+.BR wmii (1)
+the namespace of
+.B wmikeys
+can be found in /keys.
+.SH SEE ALSO
+.BR wmibar (1),
+.BR wmifs (1),
+.BR wmii (1),
+.BR wmiiwm (1),
+.BR wmimenu (1),
+.BR wmir (1)
diff --git a/cmd/wmiikeys.c b/cmd/wmiikeys.c
@@ -0,0 +1,481 @@
+/*
+ * (C)opyright MMIV-MMV 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 <X11/keysym.h>
+#include <X11/Xatom.h>
+#include <X11/cursorfont.h>
+#include <X11/Xproto.h>
+#include <X11/Xutil.h>
+
+#include "wmii.h"
+
+/* array indexes for file pointers */
+typedef enum {
+ K_CTL,
+ K_LOOKUP,
+ K_GRAB_KB,
+ K_FONT,
+ K_FG_COLOR,
+ K_BG_COLOR,
+ K_BORDER_COLOR,
+ K_LAST
+} KeyIndexes;
+
+typedef struct Shortcut Shortcut;
+
+struct Shortcut {
+ char name[MAX_BUF];
+ unsigned long mod;
+ KeyCode key;
+ Shortcut *next;
+ File *cmdfile;
+};
+
+static IXPServer *ixps = 0;
+static Display *dpy;
+static GC gc;
+static Window win;
+static Window root;
+static XRectangle krect;
+static XRectangle rect;
+static int screen_num;
+static char *sockfile = 0;
+static Container shortcuts = {0};
+static File *files[K_LAST];
+static int grabkb = 0;
+static unsigned int num_lock_mask, valid_mask;
+static char buf[MAX_BUF];
+static XFontStruct *font;
+
+static void grab_shortcut(Shortcut * s);
+static void ungrab_shortcut(Shortcut * s);
+static void draw_shortcut_box(char *text);
+static void quit(void *obj, char *arg);
+
+static Action acttbl[] = {
+ {"quit", quit},
+ {0, 0}
+};
+
+static char *version[] = {
+ "wmikeys - window manager improved keys - " VERSION "\n"
+ " (C)opyright MMIV-MMV Anselm R. Garbe\n", 0
+};
+
+static void usage()
+{
+ fprintf(stderr, "%s",
+ "usage: wmikeys [-s <socket file>] [-v]\n"
+ " -s socket file (default: /tmp/.ixp-$USER/wmikeys-$WMII_IDENT)\n"
+ " -v version info\n");
+ exit(1);
+}
+
+static void center()
+{
+ krect.x = rect.width / 2 - krect.width / 2;
+ krect.y = rect.height / 2 - krect.height / 2;
+}
+
+/* grabs shortcut on all screens */
+static void grab_shortcut(Shortcut * s)
+{
+ XGrabKey(dpy, s->key, s->mod, root,
+ True, GrabModeAsync, GrabModeAsync);
+ if (num_lock_mask) {
+ XGrabKey(dpy, s->key, s->mod | num_lock_mask, root,
+ True, GrabModeAsync, GrabModeAsync);
+ XGrabKey(dpy, s->key, s->mod | num_lock_mask | LockMask, root,
+ True, GrabModeAsync, GrabModeAsync);
+ }
+ XSync(dpy, False);
+}
+
+/*
+ * don't handle evil keys anymore, just define more shortcuts if you cannot
+ * live without evil key handling
+ */
+static void ungrab_shortcut(Shortcut * s)
+{
+ XUngrabKey(dpy, s->key, s->mod, root);
+ if (num_lock_mask) {
+ XUngrabKey(dpy, s->key, s->mod | num_lock_mask, root);
+ XUngrabKey(dpy, s->key, s->mod | num_lock_mask | LockMask, root);
+ }
+ XSync(dpy, False);
+}
+
+static void create_shortcut(File * f)
+{
+ static char *chain[8];
+ char *k;
+ size_t i, toks;
+ Shortcut *s = 0, *r = 0;
+
+ cext_strlcpy(buf, f->name, sizeof(buf));
+ toks = cext_tokenize(chain, 8, buf, ',');
+
+ for (i = 0; i < toks; i++) {
+ if (!s)
+ r = s = cext_emallocz(sizeof(Shortcut));
+ else {
+ s->next = cext_emallocz(sizeof(Shortcut));
+ s = s->next;
+ }
+ cext_strlcpy(s->name, chain[i], MAX_BUF);
+ k = strrchr(chain[i], '-');
+ if (k)
+ k++;
+ else
+ k = chain[i];
+ s->key = XKeysymToKeycode(dpy, XStringToKeysym(k));
+ s->mod = blitz_strtomod(chain[i]);
+ }
+ if (r) {
+ s->cmdfile = f;
+ cext_attach_item(&shortcuts, r);
+ grab_shortcut(r);
+ }
+}
+
+static void destroy_shortcut(Shortcut * s, int ungrab)
+{
+ if (s->next)
+ destroy_shortcut(s->next, 0);
+ if (ungrab)
+ ungrab_shortcut(s);
+ free(s);
+}
+
+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 void handle_shortcut_chain(Window w, Shortcut * processed, char *prefix, int grab)
+{
+ unsigned long mod;
+ KeyCode key;
+ Shortcut *s = processed->next;
+
+ if (grab) {
+ XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+ XMapRaised(dpy, win);
+ }
+ draw_shortcut_box(prefix);
+ next_keystroke(&mod, &key);
+
+ if ((processed->mod == mod) && (processed->key == key)) {
+ /* double shortcut */
+ emulate_key_press(mod, key);
+ } else if ((s->mod == mod) && (s->key == key)) {
+ if (s->cmdfile && s->cmdfile->content)
+ spawn(dpy, s->cmdfile->content);
+ else if (s->next) {
+ snprintf(buf, sizeof(buf), "%s/%s", prefix, s->name);
+ handle_shortcut_chain(w, s, buf, 0);
+ }
+ }
+ if (grab) {
+ XUngrabKeyboard(dpy, CurrentTime);
+ XUnmapWindow(dpy, win);
+ XSync(dpy, False);
+ }
+}
+
+static int comp_shortcut(void *comp_short, void *shortcut)
+{
+ Shortcut *comp = comp_short;
+ Shortcut *s = shortcut;
+ return (s->mod == comp->mod) && (s->key == comp->key);
+}
+
+static void handle_shortcut_gkb(Window w, unsigned long mod, KeyCode key)
+{
+ Shortcut comp, *s;
+ if (!files[K_LOOKUP]->content)
+ return;
+
+ comp.mod = mod;
+ comp.key = key;
+
+ s = cext_find_item(&shortcuts, &comp, comp_shortcut);
+ if (s && s->cmdfile && s->cmdfile->content) {
+ spawn(dpy, s->cmdfile->content);
+ return;
+ }
+ XBell(dpy, 0);
+}
+
+static void handle_shortcut(Window w, unsigned long mod, KeyCode key)
+{
+ Shortcut comp, *s;
+ if (!files[K_LOOKUP]->content)
+ return;
+
+ comp.mod = mod;
+ comp.key = key;
+
+ s = cext_find_item(&shortcuts, &comp, comp_shortcut);
+ if (s && s->cmdfile && s->cmdfile->content) {
+ spawn(dpy, s->cmdfile->content);
+ return;
+ }
+ if (s && s->next)
+ handle_shortcut_chain(w, s, s->name, 1);
+}
+
+static void quit(void *obj, char *arg)
+{
+ ixps->runlevel = SHUTDOWN;
+}
+
+static void update()
+{
+ Shortcut *s;
+ File *f, *p;
+ if (!files[K_LOOKUP]->content)
+ return;
+
+ f = ixp_walk(ixps, files[K_LOOKUP]->content);
+
+ if (!f || !is_directory(f))
+ return; /* cannot update */
+
+ /* destroy existing shortcuts if any */
+ while ((s = cext_stack_get_top_item(&shortcuts))) {
+ cext_detach_item(&shortcuts, s);
+ destroy_shortcut(s, 1);
+ }
+
+ if (grabkb) {
+ XGrabKeyboard(dpy, root, True, GrabModeAsync,
+ GrabModeAsync, CurrentTime);
+ return;
+ }
+ /* create new shortcuts */
+ for (p = f->content; p; p = p->next)
+ create_shortcut(p);
+}
+
+/*
+ * Function assumes following fs-structure:
+ *
+ * /box/style/font "<value>"
+ * /box/style/fgcolor "#RRGGBBAA"
+ * /box/style/bgcolor "#RRGGBBAA"
+ * /box/style/bordercolor "#RRGGBBAA"
+ */
+static void draw_shortcut_box(char *text)
+{
+ Draw d = { 0 };
+
+ d.font = font;
+ krect.width = XTextWidth(d.font, text, strlen(text)) + krect.height;
+ krect.height = font->ascent + font->descent + 4;
+ center();
+ XMoveResizeWindow(dpy, win, krect.x, krect.y, krect.width, krect.height);
+
+ /* default stuff */
+ d.gc = gc;
+ d.drawable = win;
+ d.data = text;
+ d.rect.y = 0;
+ d.rect.width = krect.width;
+ d.rect.height = krect.height;
+ d.bg = blitz_loadcolor(dpy, screen_num, files[K_BG_COLOR]->content);
+ d.fg = blitz_loadcolor(dpy, screen_num, files[K_FG_COLOR]->content);
+ d.border = blitz_loadcolor(dpy, screen_num, files[K_BORDER_COLOR]->content);
+ blitz_drawlabel(dpy, &d);
+}
+
+static void check_event(Connection * c)
+{
+ XEvent ev;
+
+ while (XPending(dpy)) {
+ XNextEvent(dpy, &ev);
+ switch (ev.type) {
+ case KeyPress:
+ ev.xkey.state &= valid_mask;
+ if (grabkb)
+ handle_shortcut_gkb(root, ev.xkey.state,
+ (KeyCode) ev.xkey.keycode);
+ else
+ handle_shortcut(root, ev.xkey.state,
+ (KeyCode) ev.xkey.keycode);
+ break;
+ case KeymapNotify:
+ update();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void handle_after_write(IXPServer * s, File * f)
+{
+ int i;
+ size_t len;
+
+ if (f == files[K_CTL]) {
+ for (i = 0; acttbl[i].name; i++) {
+ len = strlen(acttbl[i].name);
+ if (!strncmp(acttbl[i].name, (char *) f->content, len)) {
+ if (strlen(f->content) > len) {
+ acttbl[i].func(0, &((char *) f->content)[len + 1]);
+ } else {
+ acttbl[i].func(0, 0);
+ }
+ break;
+ }
+ }
+ } else if (f == files[K_GRAB_KB]) {
+ grabkb = blitz_strtonum(files[K_GRAB_KB]->content, 0, 1);
+ if (!grabkb) {
+ XUngrabKeyboard(dpy, CurrentTime);
+ XUnmapWindow(dpy, win);
+ XSync(dpy, False);
+ } else
+ update();
+ } else if (f == files[K_FONT]) {
+ XFreeFont(dpy, font);
+ font = blitz_getfont(dpy, files[K_FONT]->content);
+ krect = rect;
+ krect.height = font->ascent + font->descent + 4;
+ center();
+ XMoveResizeWindow(dpy, win, krect.x, krect.y, krect.width, krect.height);
+ } else if (f == files[K_LOOKUP]) {
+ update();
+ }
+ check_event(0);
+}
+
+static int dummy_error_handler(Display * dpy, XErrorEvent * err)
+{
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+ XSetWindowAttributes wa;
+ XGCValues gcv;
+
+ /* command line args */
+ for (i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
+ switch (argv[i][1]) {
+ case 'v':
+ fprintf(stdout, "%s", version[0]);
+ exit(0);
+ break;
+ case 's':
+ if (i + 1 < argc)
+ sockfile = argv[++i];
+ else
+ usage();
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ dpy = XOpenDisplay(0);
+ if (!dpy) {
+ fprintf(stderr, "%s", "wmikeys: cannot open display\n");
+ exit(1);
+ }
+ XSetErrorHandler(dummy_error_handler);
+ screen_num = DefaultScreen(dpy);
+
+ /* init */
+ ixps = wmii_setup_server(sockfile);
+
+ if (!(files[K_CTL] = ixp_create(ixps, "/ctl"))) {
+ perror("wmikeys: cannot connect IXP server");
+ exit(1);
+ }
+ files[K_CTL]->after_write = handle_after_write;
+ files[K_LOOKUP] = ixp_create(ixps, "/lookup");
+ files[K_LOOKUP]->after_write = handle_after_write;
+ files[K_GRAB_KB] = wmii_create_ixpfile(ixps, "/grabkeyb", "0");
+ files[K_GRAB_KB]->after_write = handle_after_write;
+ files[K_FONT] = wmii_create_ixpfile(ixps, "/box/font", BLITZ_FONT);
+ files[K_FONT]->after_write = handle_after_write;
+ font = blitz_getfont(dpy, files[K_FONT]->content);
+ files[K_FG_COLOR] = wmii_create_ixpfile(ixps, "/box/fgcolor", BLITZ_SEL_FG_COLOR);
+ files[K_BG_COLOR] = wmii_create_ixpfile(ixps, "/box/bgcolor", BLITZ_SEL_BG_COLOR);
+ files[K_BORDER_COLOR] = wmii_create_ixpfile(ixps, "/box/bordercolor", BLITZ_SEL_BORDER_COLOR);
+
+ wa.override_redirect = 1;
+ wa.background_pixmap = ParentRelative;
+ wa.event_mask =
+ ExposureMask | SubstructureRedirectMask | SubstructureNotifyMask;
+
+ root = RootWindow(dpy, screen_num);
+ rect.x = rect.y = 0;
+ rect.width = DisplayWidth(dpy, screen_num);
+ rect.height = DisplayHeight(dpy, screen_num);
+ krect.x = krect.y = 0;
+ krect.width = krect.height = 1;
+
+ init_lock_modifiers(dpy, &valid_mask, &num_lock_mask);
+
+ win = XCreateWindow(dpy, RootWindow(dpy, screen_num), krect.x, krect.y,
+ krect.width, krect.height, 0, DefaultDepth(dpy, screen_num),
+ CopyFromParent, DefaultVisual(dpy, screen_num),
+ CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
+ XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_left_ptr));
+ XSync(dpy, False);
+
+ gcv.function = GXcopy;
+ gcv.graphics_exposures = False;
+
+ gc = XCreateGC(dpy, win, 0, 0);
+
+ /* main event loop */
+ run_server_with_fd_support(ixps, ConnectionNumber(dpy),
+ check_event, 0);
+ deinit_server(ixps);
+ XFreeGC(dpy, gc);
+ XCloseDisplay(dpy);
+
+ return 0;
+}
diff --git a/cmd/wmiimenu.1 b/cmd/wmiimenu.1
@@ -0,0 +1,42 @@
+.TH WMIMENU 1 wmii-3
+.SH NAME
+wmimenu \- window manager improved 2 menu
+.SH SYNOPSIS
+.B wmimenu
+.B \-s
+.I socketfile
+.SH DESCRIPTION
+.SS Overview
+.B wmimenu
+is a generic, highly customizable, and efficient menu for the X Window System,
+originally designed for
+.BR wmii (1).
+It supports arbitrary, user defined menu contents, which get executed.
+Like wmii,
+.B wmimenu
+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 wmimenu
+should create.
+.TP
+.B \-v
+prints version information to stderr, then exits.
+.SS Customization
+.B wmimenu
+is customized through manipulating its filesystem namespace.
+In the default setup of
+.BR wmii (1)
+the namespace of
+.B wmimenu
+can be found in /menu.
+.SH SEE ALSO
+.BR wmibar (1),
+.BR wmifs (1),
+.BR wmii (1),
+.BR wmiiwm (1),
+.BR wmikeys (1),
+.BR wmir (1)
diff --git a/cmd/wmiimenu.c b/cmd/wmiimenu.c
@@ -0,0 +1,621 @@
+/*
+ * (C)opyright MMIV-MMV Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <time.h>
+#include <X11/Xatom.h>
+#include <X11/cursorfont.h>
+#include <X11/Xproto.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+
+#include "wmii.h"
+
+/* array indexes for file pointers */
+typedef enum {
+ M_CTL,
+ M_GEOMETRY,
+ M_PRE_COMMAND,
+ M_COMMAND,
+ M_HISTORY,
+ M_LOOKUP,
+ M_FONT,
+ M_SEL_BG_COLOR,
+ M_SEL_TEXT_COLOR,
+ M_SEL_BORDER_COLOR,
+ M_NORM_BG_COLOR,
+ M_NORM_TEXT_COLOR,
+ M_NORM_BORDER_COLOR,
+ M_LAST
+} InputIndexes;
+
+enum {
+ OFF_NEXT, OFF_PREV, OFF_CURR, OFF_LAST
+};
+
+static IXPServer *ixps = 0;
+static Display *dpy;
+static GC gc;
+static Window win;
+static XRectangle rect;
+static XRectangle mrect;
+static int screen_num;
+static char *sockfile = 0;
+static File *files[M_LAST];
+static Container items = {0};
+static Container history = {0};
+static int offset[OFF_LAST];
+static unsigned int cmdw = 0;
+static Pixmap pmap;
+static const int seek = 30; /* 30px */
+static XFontStruct *font;
+static unsigned int sel = 0;
+static Align align = SOUTH;
+
+static void check_event(Connection * c);
+static void draw_menu(void);
+static void handle_kpress(XKeyEvent * e);
+static void set_text(char *text);
+static void quit(void *obj, char *arg);
+static void display(void *obj, char *arg);
+static int update_items(char *prefix);
+
+static Action acttbl[2] = {
+ {"quit", quit},
+ {"display", display}
+};
+
+static char *version[] = {
+ "wmimenu - window manager improved menu - " VERSION "\n"
+ " (C)opyright MMIV-MMV Anselm R. Garbe\n", 0
+};
+
+static void usage()
+{
+ fprintf(stderr, "%s",
+ "usage: wmimenu [-s <socket file>] [-r] [-v]\n"
+ " -s socket file (default: /tmp/.ixp-$USER/wmimenu-%s-%s)\n"
+ " -v version info\n");
+ exit(1);
+}
+
+static void add_history(char *cmd)
+{
+ char buf[MAX_BUF];
+ snprintf(buf, MAX_BUF, "/history/%ld", (long) time(0));
+ cext_attach_item(&history, wmii_create_ixpfile(ixps, buf, cmd));
+}
+
+static void exec_item(char *cmd)
+{
+ File *item = cext_list_get_item(&items, sel);
+ char *rc = cmd;
+
+ if (!cmd || cmd[0] == 0)
+ return;
+
+ if (item && item->size)
+ rc = cmd = item->content;
+ add_history(cmd);
+
+ if (files[M_PRE_COMMAND]->content) {
+ size_t len = strlen(cmd) + files[M_PRE_COMMAND]->size + 2;
+ rc = cext_emallocz(len);
+ snprintf(rc, len, "%s %s", (char *) files[M_PRE_COMMAND]->content, cmd);
+ }
+ /* fallback */
+ spawn(dpy, rc);
+ /* cleanup */
+ if (files[M_PRE_COMMAND]->content)
+ free(rc);
+}
+
+static void quit(void *obj, char *arg)
+{
+ ixps->runlevel = SHUTDOWN;
+}
+
+static void show()
+{
+ set_text(0);
+ XMapRaised(dpy, win);
+ XSync(dpy, False);
+ update_items(files[M_COMMAND]->content);
+ draw_menu();
+ while (XGrabKeyboard
+ (dpy, RootWindow(dpy, screen_num), True, GrabModeAsync,
+ GrabModeAsync, CurrentTime) != GrabSuccess)
+ usleep(1000);
+}
+
+static void hide()
+{
+ XUngrabKeyboard(dpy, CurrentTime);
+ XUnmapWindow(dpy, win);
+ XSync(dpy, False);
+}
+
+static void display(void *obj, char *arg)
+{
+ if (!arg)
+ return;
+ if (blitz_strtonum(arg, 0, 1))
+ show();
+ else
+ hide();
+ check_event(0);
+}
+
+void set_text(char *text)
+{
+ if (files[M_COMMAND]->content) {
+ free(files[M_COMMAND]->content);
+ files[M_COMMAND]->content = 0;
+ files[M_COMMAND]->size = 0;
+ }
+ if (text && strlen(text)) {
+ files[M_COMMAND]->content = strdup(text);
+ files[M_COMMAND]->size = strlen(text);
+ }
+}
+
+static void update_offsets()
+{
+ File *item;
+ unsigned int i, w = cmdw + 2 * seek;
+
+ if (!cext_stack_get_top_item(&items))
+ return;
+
+ /* calc next offset */
+ for (i = offset[OFF_CURR]; (item = cext_list_get_item(&items, i)); i++) {
+ w += XTextWidth(font, item->content, strlen(item->content)) + mrect.height;
+ if (w > mrect.width)
+ break;
+ }
+ offset[OFF_NEXT] = i;
+
+ w = cmdw + 2 * seek;
+ for (i = offset[OFF_CURR] - 1; (i >= 0) && (item = cext_list_get_item(&items, i)); i--) {
+ w += XTextWidth(font, item->content, strlen(item->content)) + mrect.height;
+ if (w > mrect.width)
+ break;
+ }
+ offset[OFF_PREV] = i + 1;
+}
+
+static int update_items(char *pattern)
+{
+ size_t plen = pattern ? strlen(pattern) : 0, len, max = 0, size;
+ int matched = pattern ? plen == 0 : 1;
+ File *f, *p, *maxitem;
+
+ if (!files[M_LOOKUP]->content)
+ return 0;
+ f = ixp_walk(ixps, files[M_LOOKUP]->content);
+ if (!f || !is_directory(f))
+ return 0;
+
+ cmdw = 0;
+ offset[OFF_CURR] = offset[OFF_PREV] = offset[OFF_NEXT] = 0;
+ sel = 0;
+
+ while ((p = cext_stack_get_top_item(&items)))
+ cext_detach_item(&items, p);
+
+ /* build new items */
+ for (p = f->content; p; p = p->next) {
+ len = strlen(p->name);
+ if (max < len) {
+ maxitem = p;
+ max = len;
+ }
+ }
+
+ if (maxitem)
+ cmdw = XTextWidth(font, maxitem->name, max) + mrect.height;
+
+ for (p = f->content; p; p = p->next) {
+ if (matched || !strncmp(pattern, p->name, plen)) {
+ cext_attach_item(&items, p);
+ p->parent = 0; /* HACK to prevent doubled items */
+ }
+ }
+
+ for (p = f->content; p; p = p->next) {
+ if (p->parent && strstr(p->name, pattern))
+ cext_attach_item(&items, p);
+ else
+ p->parent = f; /* restore HACK */
+ }
+
+ size = cext_sizeof(&items);
+ update_offsets();
+ return size;
+}
+
+/* creates draw structs for menu mode drawing */
+static void draw_menu()
+{
+ Draw d = { 0 };
+ unsigned int offx = 0;
+ int i = 0;
+ File *item = 0, *selitem = cext_list_get_item(&items, sel);
+
+ d.gc = gc;
+ d.font = font;
+ d.drawable = pmap;
+ d.rect = mrect;
+ d.rect.x = 0;
+ d.rect.y = 0;
+ d.bg = blitz_loadcolor(dpy, screen_num, files[M_NORM_BG_COLOR]->content);
+ d.border = blitz_loadcolor(dpy, screen_num, files[M_NORM_BORDER_COLOR]->content);
+ blitz_drawlabelnoborder(dpy, &d);
+
+ /* print command */
+ d.align = WEST;
+ d.font = font;
+ d.fg = blitz_loadcolor(dpy, screen_num, files[M_NORM_TEXT_COLOR]->content);
+ d.data = files[M_COMMAND]->content;
+ if (cmdw && selitem)
+ d.rect.width = cmdw;
+ offx += d.rect.width;
+ blitz_drawlabelnoborder(dpy, &d);
+
+ d.align = CENTER;
+ if (selitem) {
+ d.bg = blitz_loadcolor(dpy, screen_num, files[M_NORM_BG_COLOR]->content);
+ d.fg = blitz_loadcolor(dpy, screen_num, files[M_NORM_TEXT_COLOR]->content);
+ d.data = offset[OFF_CURR] ? "<" : 0;
+ d.rect.x = offx;
+ d.rect.width = seek;
+ offx += d.rect.width;
+ blitz_drawlabelnoborder(dpy, &d);
+
+ /* determine maximum items */
+ for (i = offset[OFF_CURR]; (item = cext_list_get_item(&items, i)) && (i < offset[OFF_NEXT]); i++) {
+ d.data = item->name;
+ d.rect.x = offx;
+ d.rect.width = XTextWidth(d.font, d.data, strlen(d.data)) + mrect.height;
+ offx += d.rect.width;
+ /*fprintf(stderr, "%s (%d, %d, %d, %d)\n", item->name, d.rect.x, d.rect.y, d.rect.width, d.rect.height);*/
+ if (selitem == item) {
+ d.bg = blitz_loadcolor(dpy, screen_num, files[M_SEL_BG_COLOR]->content);
+ d.fg = blitz_loadcolor(dpy, screen_num, files[M_SEL_TEXT_COLOR]->content);
+ d.border = blitz_loadcolor(dpy, screen_num, files[M_SEL_BORDER_COLOR]-> content);
+ blitz_drawlabel(dpy, &d);
+ } else {
+ d.bg = blitz_loadcolor(dpy, screen_num, files[M_NORM_BG_COLOR]->content);
+ d.fg = blitz_loadcolor(dpy, screen_num, files[M_NORM_TEXT_COLOR]->content);
+ d.border = blitz_loadcolor(dpy, screen_num, files[M_NORM_BORDER_COLOR]->content);
+ blitz_drawlabelnoborder(dpy, &d);
+ }
+ }
+
+ d.bg = blitz_loadcolor(dpy, screen_num, files[M_NORM_BG_COLOR]->content);
+ d.fg = blitz_loadcolor(dpy, screen_num, files[M_NORM_TEXT_COLOR]->content);
+ d.data = item ? ">" : 0;
+ d.rect.x = mrect.width - seek;
+ d.rect.width = seek;
+ blitz_drawlabelnoborder(dpy, &d);
+ }
+ XCopyArea(dpy, pmap, win, gc, 0, 0, mrect.width, mrect.height, 0, 0);
+ XSync(dpy, False);
+}
+
+static void handle_kpress(XKeyEvent * e)
+{
+ KeySym ksym;
+ char buf[32];
+ int num;
+ static char text[4096];
+ size_t len = 0, size = cext_sizeof(&items);
+ File *selitem = cext_list_get_item(&items, sel);
+ File *hist = cext_stack_get_top_item(&history);
+
+ text[0] = 0;
+ if (files[M_COMMAND]->content) {
+ cext_strlcpy(text, files[M_COMMAND]->content, sizeof(text));
+ len = strlen(text);
+ }
+ buf[0] = 0;
+ num = XLookupString(e, buf, sizeof(buf), &ksym, 0);
+
+ if (IsFunctionKey(ksym) || IsKeypadKey(ksym)
+ || IsMiscFunctionKey(ksym) || IsPFKey(ksym)
+ || IsPrivateKeypadKey(ksym))
+ return;
+
+ /* first check if a control mask is omitted */
+ if (e->state & ShiftMask) {
+ if (ksym == XK_ISO_Left_Tab)
+ ksym = XK_Left;
+ } else if (e->state & ControlMask) {
+ switch (ksym) {
+ case XK_E:
+ case XK_e:
+ ksym = XK_End;
+ break;
+ case XK_H:
+ case XK_h:
+ ksym = XK_BackSpace;
+ break;
+ case XK_J:
+ case XK_j:
+ ksym = XK_Return;
+ break;
+ case XK_U:
+ case XK_u:
+ set_text(0);
+ update_items(0);
+ draw_menu();
+ return;
+ break;
+ default: /* ignore other control sequences */
+ return;
+ break;
+ }
+ }
+ switch (ksym) {
+ case XK_Left:
+ if (!selitem)
+ return;
+ if (sel > 0) {
+ selitem = cext_list_get_item(&items, --sel);
+ set_text(selitem->name);
+ } else
+ return;
+ break;
+ case XK_Right:
+ case XK_Tab:
+ if (!selitem)
+ return;
+ if (sel < size - 1) {
+ selitem = cext_list_get_item(&items, ++sel);
+ set_text(selitem->name);
+ } else
+ return;
+ break;
+ case XK_Down:
+ if (hist) {
+ set_text(hist->content);
+ cext_stack_top_item(&history, cext_list_get_next_item(&items, hist));
+ }
+ update_items(files[M_COMMAND]->content);
+ break;
+ case XK_Up:
+ if (hist) {
+ set_text(hist->content);
+ cext_stack_top_item(&history, cext_list_get_prev_item(&items, hist));
+ }
+ update_items(files[M_COMMAND]->content);
+ break;
+ case XK_Return:
+ if (selitem)
+ exec_item(selitem->name);
+ else if (text)
+ exec_item(text);
+ case XK_Escape:
+ hide();
+ break;
+ case XK_BackSpace:
+ if (len) {
+ size_t i = len;
+ if (i) {
+ do
+ text[--i] = 0;
+ while (size && i && size == update_items(text));
+ }
+ set_text(text);
+ update_items(files[M_COMMAND]->content);
+ }
+ break;
+ default:
+ if ((num == 1) && !iscntrl((int) buf[0])) {
+ buf[num] = 0;
+ if (len > 0)
+ cext_strlcat(text, buf, sizeof(text));
+ else
+ cext_strlcpy(text, buf, sizeof(text));
+ set_text(text);
+ update_items(files[M_COMMAND]->content);
+ }
+ }
+ if (selitem) {
+ if (sel < offset[OFF_CURR]) {
+ offset[OFF_CURR] = offset[OFF_PREV];
+ update_offsets();
+ } else if (sel >= offset[OFF_NEXT]) {
+ offset[OFF_CURR] = offset[OFF_NEXT];
+ update_offsets();
+ }
+ }
+ draw_menu();
+}
+
+static void check_event(Connection * c)
+{
+ XEvent ev;
+
+ while (XPending(dpy)) {
+ XNextEvent(dpy, &ev);
+ switch (ev.type) {
+ case KeyPress:
+ handle_kpress(&ev.xkey);
+ break;
+ case Expose:
+ if (ev.xexpose.count == 0) {
+ draw_menu();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void update_geometry()
+{
+ mrect = rect;
+ mrect.height = font->ascent + font->descent + 4;
+ if (align == SOUTH)
+ mrect.y = rect.height - mrect.height;
+ XMoveResizeWindow(dpy, win, mrect.x, mrect.y, mrect.width, mrect.height);
+ XSync(dpy, False);
+ XFreePixmap(dpy, pmap);
+ pmap = XCreatePixmap(dpy, win, mrect.width, mrect.height, DefaultDepth(dpy, screen_num));
+ XSync(dpy, False);
+}
+
+static void handle_after_write(IXPServer * s, File * f)
+{
+ int i;
+ size_t len;
+
+ if (files[M_CTL] == f) {
+ for (i = 0; i < 2; i++) {
+ len = strlen(acttbl[i].name);
+ if (!strncmp(acttbl[i].name, (char *) f->content, len)) {
+ if (strlen(f->content) > len) {
+ acttbl[i].func(0, &((char *) f->content)[len + 1]);
+ } else {
+ acttbl[i].func(0, 0);
+ }
+ break;
+ }
+ }
+ } else if (files[M_GEOMETRY] == f) {
+ if (f->content) {
+ if (!strncmp(f->content, "south", 6))
+ align = SOUTH;
+ else if(!strncmp(f->content, "north", 6))
+ align = NORTH;
+ update_geometry();
+ draw_menu();
+ }
+ } else if (files[M_FONT] == f) {
+ XFreeFont(dpy, font);
+ font = blitz_getfont(dpy, files[M_FONT]->content);
+ update_geometry();
+ draw_menu();
+ } else if (files[M_COMMAND] == f) {
+ update_items(files[M_COMMAND]->content);
+ draw_menu();
+ }
+ check_event(0);
+}
+
+static void handle_before_read(IXPServer * s, File * f)
+{
+ char buf[64];
+ if (f != files[M_GEOMETRY])
+ return;
+ snprintf(buf, sizeof(buf), "%d,%d,%d,%d", mrect.x, mrect.y,
+ mrect.width, mrect.height);
+ if (f->content)
+ free(f->content);
+ f->content = strdup(buf);
+ f->size = strlen(buf);
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+ XSetWindowAttributes wa;
+ XGCValues gcv;
+
+ /* command line args */
+ for (i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
+ switch (argv[i][1]) {
+ case 'v':
+ fprintf(stdout, "%s", version[0]);
+ exit(0);
+ break;
+ case 's':
+ if (i + 1 < argc)
+ sockfile = argv[++i];
+ else
+ usage();
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ dpy = XOpenDisplay(0);
+ if (!dpy) {
+ fprintf(stderr, "%s", "wmimenu: cannot open display\n");
+ exit(1);
+ }
+ screen_num = DefaultScreen(dpy);
+
+ ixps = wmii_setup_server(sockfile);
+
+ /* init */
+ if (!(files[M_CTL] = ixp_create(ixps, "/ctl"))) {
+ perror("wmimenu: cannot connect IXP server");
+ exit(1);
+ }
+ files[M_CTL]->after_write = handle_after_write;
+ files[M_GEOMETRY] = ixp_create(ixps, "/geometry");
+ files[M_GEOMETRY]->before_read = handle_before_read;
+ files[M_GEOMETRY]->after_write = handle_after_write;
+ files[M_PRE_COMMAND] = ixp_create(ixps, "/precmd");
+ files[M_COMMAND] = ixp_create(ixps, "/cmd");
+ files[M_COMMAND]->after_write = handle_after_write;
+ files[M_HISTORY] = ixp_create(ixps, "/history");
+ add_history("");
+ files[M_LOOKUP] = ixp_create(ixps, "/lookup");
+ files[M_FONT] = wmii_create_ixpfile(ixps, "/font", BLITZ_FONT);
+ files[M_FONT]->after_write = handle_after_write;
+ font = blitz_getfont(dpy, files[M_FONT]->content);
+ files[M_SEL_BG_COLOR] = wmii_create_ixpfile(ixps, "/sstyle/bgcolor", BLITZ_SEL_BG_COLOR);
+ files[M_SEL_TEXT_COLOR] = wmii_create_ixpfile(ixps, "/sstyle/fgcolor", BLITZ_SEL_FG_COLOR);
+ files[M_SEL_BORDER_COLOR] = wmii_create_ixpfile(ixps, "/sstyle/bordercolor", BLITZ_SEL_BORDER_COLOR);
+ files[M_NORM_BG_COLOR] = wmii_create_ixpfile(ixps, "/nstyle/bgcolor", BLITZ_NORM_BG_COLOR);
+ files[M_NORM_TEXT_COLOR] = wmii_create_ixpfile(ixps, "/nstyle/fgcolor", BLITZ_NORM_FG_COLOR);
+ files[M_NORM_BORDER_COLOR] = wmii_create_ixpfile(ixps, "/nstyle/bordercolor", BLITZ_NORM_BORDER_COLOR);
+
+ wa.override_redirect = 1;
+ wa.background_pixmap = ParentRelative;
+ wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask
+ | SubstructureRedirectMask | SubstructureNotifyMask;
+
+ rect.x = rect.y = 0;
+ rect.width = DisplayWidth(dpy, screen_num);
+ rect.height = DisplayHeight(dpy, screen_num);
+ mrect = rect;
+ mrect.height = font->ascent + font->descent + 4;
+ mrect.y = rect.height - mrect.height;
+
+ win = XCreateWindow(dpy, RootWindow(dpy, screen_num), mrect.x, mrect.y,
+ mrect.width, mrect.height, 0, DefaultDepth(dpy, screen_num),
+ CopyFromParent, DefaultVisual(dpy, screen_num),
+ CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
+ XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_xterm));
+ XSync(dpy, False);
+
+ /* window pixmap */
+ gcv.function = GXcopy;
+ gcv.graphics_exposures = False;
+
+ gc = XCreateGC(dpy, win, 0, 0);
+ pmap = XCreatePixmap(dpy, win, mrect.width, mrect.height, DefaultDepth(dpy, screen_num));
+
+ /* main event loop */
+ run_server_with_fd_support(ixps, ConnectionNumber(dpy), check_event, 0);
+ deinit_server(ixps);
+ XFreePixmap(dpy, pmap);
+ XFreeGC(dpy, gc);
+ XCloseDisplay(dpy);
+
+ return 0;
+}
diff --git a/cmd/wmiiplumb.c b/cmd/wmiiplumb.c
@@ -0,0 +1,92 @@
+/*
+ * (C)opyright MMIV-MMV Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+static char *version[] = {
+ "wmiplumb - window manager improved plumb - " VERSION "\n"
+ " (C)opyright MMIV-MMV Anselm R. Garbe\n", 0
+};
+
+static void usage()
+{
+ fprintf(stderr, "%s\n",
+ "usage: wmiplumb [-v]\n" " -v version info\n");
+ exit(1);
+}
+
+static void print_sel(Display * dpy, Window w, XSelectionEvent * e)
+{
+ Atom typeret;
+ int format;
+ unsigned long nitems, bytesleft;
+ unsigned char *data;
+
+ XGetWindowProperty(dpy, w, e->property, 0L, 4096L, False,
+ AnyPropertyType, &typeret, &format,
+ &nitems, &bytesleft, &data);
+ if (format == 8) {
+ int i;
+ for (i = 0; i < nitems; i++)
+ putchar(data[i]);
+ putchar('\n');
+ }
+ XDeleteProperty(dpy, w, e->property);
+}
+
+int main(int argc, char **argv)
+{
+ Display *dpy;
+ Atom xa_clip_string;
+ Window w;
+ XEvent ev;
+ int pdone = 0;
+
+
+ /* command line args */
+ if (argc > 1) {
+ if (!strncmp(argv[1], "-v", 3)) {
+ fprintf(stdout, "%s", version[0]);
+ exit(0);
+ } else
+ usage();
+ }
+ dpy = XOpenDisplay(0);
+ if (!dpy) {
+ fprintf(stderr, "%s", "wmiplumb: cannot open display\n");
+ exit(1);
+ }
+ xa_clip_string = XInternAtom(dpy, "PLUMB_STRING", False);
+ w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 10, 10, 200, 200,
+ 1, CopyFromParent, CopyFromParent);
+ while (1 && !pdone) {
+ XConvertSelection(dpy, XA_PRIMARY, XA_STRING, xa_clip_string,
+ w, CurrentTime);
+ XFlush(dpy);
+ XNextEvent(dpy, &ev);
+ switch (ev.type) {
+ case SelectionNotify:
+ if (ev.xselection.property != None)
+ print_sel(dpy, w, &ev.xselection);
+ else
+ putchar('\n');
+ XDestroyWindow(dpy, w);
+ XCloseDisplay(dpy);
+ pdone = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ return 0;
+ /*
+ * XDestroyWindow(dpy, w); XCloseDisplay(dpy); return 1;
+ */
+}
diff --git a/cmd/wmiir.1 b/cmd/wmiir.1
@@ -0,0 +1,71 @@
+.TH WMIR 1 wmii-3
+.SH NAME
+wmir \- window manager improved 2 remote
+.SH SYNOPSIS
+.B wmir
+.RB [ \-s
+.IR socketfile ]
+.I action
+.I action_arg
+[...]
+.br
+.B wmir
+.RB [ \-s
+.IR socketfile ]
+.B \-f
+.br
+.B wmir
+.B \-v
+.SH DESCRIPTION
+.SS Overview
+.B wmir
+is a client to access wmi* fileservers for the command line and
+scripts. It can be used to configure wmii(1).
+.SS Options
+.TP
+.BI \-s " socketfile"
+lets you specify the socketfile to which
+.B wmir
+a connection will be established. If the environment variable
+.B WMIR_SOCKET
+is set and points to a socket file, wmir will use that file, if this
+option is not supplied.
+.TP
+.B \-f
+reads from stdin, useful for interactive wmir sessions or for
+scripts that write/read a bunch of data, because this speeds things up
+due to missing process creation/destruction, ie., a hack.
+.TP
+.B \-v
+prints version information to stderr, then exits.
+.TP
+The syntax of the actions is as follows:
+.TP
+.B create <path/file> [<value>]
+creates file
+.TP
+.B write <file> <value>
+writes value to a file
+.TP
+.B read <path/file>
+reads file or directory contents
+.TP
+.B remove <path/file>
+removes file or directory tree
+.SH ENVIRONMENT
+.TP
+WMIR_SOCKET
+See above.
+.SH EXAMPLES
+.TP
+$ wmir read /
+This gives you an idea about what the wmii filesystem currently looks like.
+.TP
+$ wmir write /wm/ctl quit
+.SH SEE ALSO
+.BR wmibar (1),
+.BR wmifs (1),
+.BR wmii (1),
+.BR wmiiwm (1),
+.BR wmikeys (1),
+.BR wmimenu (1)
diff --git a/cmd/wmiir.c b/cmd/wmiir.c
@@ -0,0 +1,225 @@
+/*
+ * (C)opyright MMIV-MMV Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ixp.h"
+
+static IXPClient *c;
+static int exit_code = 0;
+
+static char *version[] = {
+ "wmir - window manager improved remote - " VERSION "\n"
+ " (C)opyright MMIV-MMV Anselm R. Garbe\n", 0
+};
+
+static void usage()
+{
+ fprintf(stderr, "%s",
+ "usage: wmir [-s <socket file>] [-v] <action> <action_arg> [...]\n"
+ " -s socket file (default: $WMIR_SOCKET)\n"
+ " -f read actions from stdin\n"
+ " -v version info\n"
+ "actions:\n"
+ " create <file> [<content>] -- creates and optionally writes content to a file\n"
+ " write <file> <content> -- writes content to a file\n"
+ " read <directory/file> -- reads file or directory contents\n"
+ " remove <directory/file> -- removes file or directory, use with care!\n");
+ exit(1);
+}
+
+static void perform(char *action, char *file, char *content)
+{
+ size_t out_len = 0;
+ char output[2050];
+ int crt, fd = -1;
+
+ if (!action)
+ return;
+
+ crt = !strncmp(action, "create", 7);
+ if (!strncmp(action, "write", 6) || crt) {
+ if (!file)
+ return;
+ /* create file first */
+ if (crt) {
+ c->create(c, file);
+ if (c->errstr) {
+ fprintf(stderr, "wmir: error: create %s: %s\n", file,
+ c->errstr);
+ exit_code = 1;
+ return;
+ }
+ }
+ if (!content)
+ return;
+ fd = c->open(c, file);
+ if (c->errstr) {
+ fprintf(stderr, "wmir: error: open %s: %s\n", file, c->errstr);
+ exit_code = 1;
+ return;
+ }
+ c->write(c, fd, content, strlen(content));
+ if (c->errstr) {
+ fprintf(stderr, "wmir: error: write %s: %s\n", file,
+ c->errstr);
+ exit_code = 1;
+ if (!strncmp(c->errstr, DEAD_SERVER, strlen(DEAD_SERVER) + 1))
+ return;
+ }
+ } else if (!strncmp(action, "read", 5)) {
+ if (!file)
+ return;
+ fd = c->open(c, file);
+ if (c->errstr) {
+ fprintf(stderr, "wmir: error: open %s: %s\n", file, c->errstr);
+ exit_code = 1;
+ return;
+ }
+ do {
+ out_len = c->read(c, fd, output, 2048);
+ if (c->errstr) {
+ fprintf(stderr, "wmir: error: read %s: %s\n", file,
+ c->errstr);
+ exit_code = 1;
+ if (!strncmp
+ (c->errstr, DEAD_SERVER, strlen(DEAD_SERVER) + 1))
+ return;
+ break;
+ }
+ output[out_len] = 0;
+ fprintf(stdout, "%s", output);
+ }
+ while (out_len == 2048);
+ fprintf(stdout, "%s", "\n");
+ } else if (!strncmp(action, "remove", 7)) {
+ if (!file)
+ return;
+ c->remove(c, file);
+ if (c->errstr) {
+ fprintf(stderr, "wmir: error: remove %s: %s\n", file,
+ c->errstr);
+ exit_code = 1;
+ return;
+ }
+ }
+ if (fd != -1) {
+ c->close(c, fd);
+ if (c->errstr) {
+ fprintf(stderr, "wmir: error: close %s: %s\n", file,
+ c->errstr);
+ exit_code = 1;
+ return;
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ int i = 0, read_stdin = 0;
+ char line[4096], *p;
+ char *sockfile = getenv("WMIR_SOCKET");
+
+ /* command line args */
+ if (argc > 1) {
+ for (i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
+ switch (argv[i][1]) {
+ case 'v':
+ fprintf(stderr, "%s", version[0]);
+ exit(0);
+ break;
+ case 's':
+ if (i + 1 < argc) {
+ sockfile = argv[++i];
+ } else {
+ usage();
+ }
+ break;
+ case 'f':
+ read_stdin = 1;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+ }
+ if ((argc <= 1) || (!read_stdin && (i + 1) >= argc)) {
+ fprintf(stderr, "%s", "wmir: arguments: ");
+ for (i = 1; i < argc; i++)
+ fprintf(stderr, "%s, ", argv[i]);
+ fprintf(stderr, "%s", "\n");
+ usage();
+ }
+ if (!sockfile) {
+ fprintf(stderr, "%s",
+ "wmir: error: WMIR_SOCKET environment not set\n");
+ usage();
+ }
+ /* open socket */
+ if (!(c = init_ixp_client(sockfile))) {
+ fprintf(stderr, "wmir: cannot connect to server '%s'\n", sockfile);
+ exit(1);
+ }
+ if (read_stdin) {
+ /* simple shell */
+ char *action, *file, *content;
+ while (fgets(line, 4096, stdin)) {
+ p = line;
+ while (*p != 0 && (*p == ' ' || *p == '\t'))
+ p++;
+ if (*p == 0)
+ continue; /* empty line */
+ if (strncmp(p, "create ", 7) &&
+ strncmp(p, "write ", 6) &&
+ strncmp(p, "read ", 5) && strncmp(p, "remove ", 7))
+ continue;
+
+ action = p;
+ while (*p != 0 && *p != ' ' && *p != '\t' && *p != '\n')
+ p++;
+ if (*p == 0 || *p == '\n')
+ continue; /* ignore bogus command */
+ *p = 0;
+ p++;
+ while (*p != 0 && (*p == ' ' || *p == '\t'))
+ p++;
+ if (*p == 0)
+ continue; /* ignore bogus command */
+ file = p;
+ while (*p != 0 && *p != ' ' && *p != '\t' && *p != '\n')
+ p++;
+ if (*p == 0 || *p == '\n') {
+ content = 0;
+ *p = 0;
+ } else {
+ *p = 0;
+ p++;
+ content = p;
+ }
+ if (file[0] == 0)
+ continue;
+ if (content) {
+ static size_t len;
+ if ((len = strlen(content)))
+ content[len - 1] = 0;
+ }
+ perform(action, file, content);
+ if (c->errstr)
+ fprintf(stderr, "wmir: error: read %s: %s\n", file,
+ c->errstr);
+ }
+ } else {
+ perform(argv[i], argv[i + 1], (i + 2) < argc ? argv[i + 2] : 0);
+ }
+
+ if (c->errstr) {
+ deinit_client(c);
+ exit_code = 1;
+ }
+ return exit_code;
+}
diff --git a/cmd/wmiir2.c b/cmd/wmiir2.c
@@ -0,0 +1,243 @@
+/*
+ * (C)opyright MMIV-MMV Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../libixp2/ixp.h"
+
+#include <cext.h>
+
+typedef struct {
+ char *name;
+ int (*cmd) (char **argv);
+ int min_argc;
+} Command;
+
+static int xcreate(char **argv);
+static int xread(char **argv);
+static int xwrite(char **argv);
+static int xremove(char **argv);
+static Command cmds[] = {
+ {"create", xcreate, 2},
+ {"read", xread, 1},
+ {"write", xwrite, 2},
+ {"remove", xremove, 1},
+ {0, 0}
+};
+static IXPClient c = { 0 };
+
+static char *version[] = {
+ "wmir - window manager improved remote - " VERSION "\n"
+ " (C)opyright MMIV-MMV Anselm R. Garbe\n", 0
+};
+
+static void usage()
+{
+ fprintf(stderr, "%s",
+ "usage: wmir [-s <socket file>] [-v] <command> <args> [...]\n"
+ " -s socket file (default: $WMIR_SOCKET)\n"
+ " -f read commands from stdin\n"
+ " -v version info\n"
+ "commands:\n"
+ " create <file> <content> -- creates file\n"
+ " read <file/directory> -- reads file/directory contents\n"
+ " write <file> <content> -- writes content to a file\n"
+ " remove <file/directory> -- removes file\n");
+ exit(1);
+}
+
+static u32 write_data(u32 fid, u8 * data, u32 count)
+{
+ u32 len, i, runs = count / c.fcall.iounit;
+
+ for (i = 0; i <= runs; i++) {
+ /* write */
+ len = count - (i * c.fcall.iounit);
+ if (len > c.fcall.iounit)
+ len = c.fcall.iounit;
+ if (ixp_client_write
+ (&c, fid, i * c.fcall.iounit, len,
+ &data[i * c.fcall.iounit]) != count) {
+ fprintf(stderr, "wmir: cannot write file: %s\n", c.errstr);
+ return 0;
+ }
+ }
+ return count;
+}
+
+static int xcreate(char **argv)
+{
+ u32 fid;
+ char *p = strrchr(argv[0], '/');
+
+ fid = c.root_fid << 2;
+ /* walk to bottom-most directory */
+ *p = 0;
+ if (!ixp_client_walk(&c, fid, argv[0])) {
+ fprintf(stderr, "wmir: cannot walk to %s: %s\n", argv[0],
+ c.errstr);
+ return 1;
+ }
+ /* create */
+ p++;
+ if (!ixp_client_create(&c, fid, p, (u32) 0xff, IXP_OWRITE)) {
+ fprintf(stderr, "wmir: cannot create file: %s\n", c.errstr);
+ return 1;
+ }
+ write_data(fid, (u8 *) argv[1], strlen(argv[1]));
+ return !ixp_client_close(&c, fid);
+}
+
+static int xwrite(char **argv)
+{
+ /* open */
+ u32 fid = c.root_fid << 2;
+ if (!ixp_client_open(&c, fid, argv[0], IXP_OWRITE)) {
+ fprintf(stderr, "wmir: cannot open file: %s\n", c.errstr);
+ return 1;
+ }
+ write_data(fid, (u8 *) argv[1], strlen(argv[1]));
+ return !ixp_client_close(&c, fid);
+}
+
+static void print_directory(void *result, u32 msize)
+{
+ void *p = result;
+ static Stat stat, zerostat = { 0 };
+ u32 len = 0;
+ do {
+ p = ixp_dec_stat(p, &stat);
+ len += stat.size + sizeof(u16);
+ if (stat.qid.type == IXP_QTDIR)
+ fprintf(stdout, "%s/\n", stat.name);
+ else
+ fprintf(stdout, "%s\n", stat.name);
+ stat = zerostat;
+ }
+ while (len < msize);
+}
+
+static int xread(char **argv)
+{
+ u32 count, fid = c.root_fid << 2;
+ int is_directory = FALSE;
+ static u8 result[IXP_MAX_MSG];
+
+ /* open */
+ if (!ixp_client_open(&c, fid, argv[0], IXP_OREAD)) {
+ fprintf(stderr, "wmir: cannot open file: %s\n", c.errstr);
+ return 1;
+ }
+ is_directory = !c.fcall.nwqid || (c.fcall.qid.type == IXP_QTDIR);
+ /* read */
+ if (!(count = ixp_client_read(&c, fid, 0, result, IXP_MAX_MSG))
+ && c.errstr) {
+ fprintf(stderr, "wmir: cannot read file: %s\n", c.errstr);
+ return 1;
+ }
+ if (count) {
+ if (is_directory)
+ print_directory(result, count);
+ else {
+ u32 i;
+ for (i = 0; i < count; i++)
+ putchar(result[i]);
+ }
+ }
+ return !ixp_client_close(&c, fid);
+}
+
+static int xremove(char **argv)
+{
+ u32 fid;
+
+ /* remove */
+ fid = c.root_fid << 2;
+ if (!ixp_client_remove(&c, fid, argv[0])) {
+ fprintf(stderr, "wmir: cannot remove file: %s\n", c.errstr);
+ return 1;
+ }
+ return 0;
+}
+
+static int perform_cmd(int argc, char **argv)
+{
+ int i;
+ for (i = 0; cmds[i].name; i++)
+ if (!strncmp(cmds[i].name, argv[0], strlen(cmds[i].name))) {
+ if (cmds[i].min_argc <= argc)
+ return cmds[i].cmd(&argv[1]);
+ else
+ usage();
+ }
+ /* bogus command */
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+ int i = 0, ret, read_stdin = 0;
+ char line[4096];
+ char *sockfile = getenv("WMIR_SOCKET");
+
+ /* command line args */
+ if (argc > 1) {
+ for (i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
+ switch (argv[i][1]) {
+ case 'v':
+ fprintf(stderr, "%s", version[0]);
+ exit(0);
+ break;
+ case 's':
+ if (i + 1 < argc)
+ sockfile = argv[++i];
+ else
+ usage();
+ break;
+ case 'f':
+ read_stdin = 1;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+ }
+ if ((argc <= 1) || (!read_stdin && (i + 1) >= argc)) {
+ fprintf(stderr, "%s", "wmir: arguments: ");
+ for (i = 1; i < argc; i++)
+ fprintf(stderr, "%s, ", argv[i]);
+ fprintf(stderr, "%s", "\n");
+ usage();
+ }
+ if (!sockfile) {
+ fprintf(stderr, "%s",
+ "wmir: error: WMIR_SOCKET environment not set\n");
+ usage();
+ }
+ /* open socket */
+ if (!ixp_client_init(&c, sockfile)) {
+ fprintf(stderr, "wmir: %s\n", c.errstr);
+ exit(1);
+ }
+ /* wether perform directly or read from stdin */
+ if (read_stdin) {
+ char *_argv[3];
+ int _argc;
+ while (fgets(line, 4096, stdin))
+ if ((_argc = cext_tokenize(_argv, 3, line, ' '))) {
+ if ((ret = perform_cmd(_argc, _argv)))
+ break;
+ }
+ } else
+ ret = perform_cmd(argc - (i + 1), &argv[i]);
+
+ /* close socket */
+ ixp_client_deinit(&c);
+
+ return ret;
+}
diff --git a/cmd/wmiiwarp.c b/cmd/wmiiwarp.c
@@ -0,0 +1,54 @@
+/*
+ * (C)opyright MMIV-MMV Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+
+static char *version[] = {
+ "wmiwarp - window manager improved warp - " VERSION "\n"
+ " (C)opyright MMIV-MMV Anselm R. Garbe\n", 0
+};
+
+static void usage()
+{
+ fprintf(stderr,
+ "usage: wmiwarp [-v] <x>,<y>\n" " -v version info\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ Display *dpy;
+ int x, y;
+
+ /* command line args */
+ if (argc != 2)
+ usage();
+ if (!strncmp(argv[1], "-v", 2)) {
+ fprintf(stdout, "%s", version[0]);
+ exit(0);
+ }
+ dpy = XOpenDisplay(0);
+ if (!dpy) {
+ fprintf(stderr, "%s", "wmiwarp: cannot open display\n");
+ exit(1);
+ }
+ if (!strncmp(argv[1], "center", 7)) {
+ x = DisplayWidth(dpy, DefaultScreen(dpy)) / 2;
+ y = DisplayHeight(dpy, DefaultScreen(dpy)) / 2;
+ } else if (sscanf(argv[1], "%d,%d", &x, &y) != 2) {
+ XCloseDisplay(dpy);
+ usage();
+ }
+ XWarpPointer(dpy, None, RootWindow(dpy, DefaultScreen(dpy)),
+ 0, 0, 0, 0, x, y);
+ XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
+ XCloseDisplay(dpy);
+ return 0;
+}
diff --git a/cmd/wmikeys.1 b/cmd/wmikeys.1
@@ -1,45 +0,0 @@
-.TH WMIKEYS 1 wmii-3
-.SH NAME
-wmikeys \- window manager improved 2 keys
-.SH SYNOPSIS
-.B wmikeys
-.B \-s
-.I socketfile
-.SH DESCRIPTION
-.SS Overview
-.B wmikeys
-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 wmikeys
-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 wmikeys
-should create.
-.TP
-.B \-v
-prints version information to stderr, then exits.
-.SS Customization
-.B wmikeys
-is customized through manipulating its filesystem namespace.
-In the default setup of
-.BR wmii (1)
-the namespace of
-.B wmikeys
-can be found in /keys.
-.SH SEE ALSO
-.BR wmibar (1),
-.BR wmifs (1),
-.BR wmii (1),
-.BR wmiiwm (1),
-.BR wmimenu (1),
-.BR wmir (1)
diff --git a/cmd/wmikeys.c b/cmd/wmikeys.c
@@ -1,481 +0,0 @@
-/*
- * (C)opyright MMIV-MMV 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 <X11/keysym.h>
-#include <X11/Xatom.h>
-#include <X11/cursorfont.h>
-#include <X11/Xproto.h>
-#include <X11/Xutil.h>
-
-#include "wmii.h"
-
-/* array indexes for file pointers */
-typedef enum {
- K_CTL,
- K_LOOKUP,
- K_GRAB_KB,
- K_FONT,
- K_FG_COLOR,
- K_BG_COLOR,
- K_BORDER_COLOR,
- K_LAST
-} KeyIndexes;
-
-typedef struct Shortcut Shortcut;
-
-struct Shortcut {
- char name[MAX_BUF];
- unsigned long mod;
- KeyCode key;
- Shortcut *next;
- File *cmdfile;
-};
-
-static IXPServer *ixps = 0;
-static Display *dpy;
-static GC gc;
-static Window win;
-static Window root;
-static XRectangle krect;
-static XRectangle rect;
-static int screen_num;
-static char *sockfile = 0;
-static Container shortcuts = {0};
-static File *files[K_LAST];
-static int grabkb = 0;
-static unsigned int num_lock_mask, valid_mask;
-static char buf[MAX_BUF];
-static XFontStruct *font;
-
-static void grab_shortcut(Shortcut * s);
-static void ungrab_shortcut(Shortcut * s);
-static void draw_shortcut_box(char *text);
-static void quit(void *obj, char *arg);
-
-static Action acttbl[] = {
- {"quit", quit},
- {0, 0}
-};
-
-static char *version[] = {
- "wmikeys - window manager improved keys - " VERSION "\n"
- " (C)opyright MMIV-MMV Anselm R. Garbe\n", 0
-};
-
-static void usage()
-{
- fprintf(stderr, "%s",
- "usage: wmikeys [-s <socket file>] [-v]\n"
- " -s socket file (default: /tmp/.ixp-$USER/wmikeys-$WMII_IDENT)\n"
- " -v version info\n");
- exit(1);
-}
-
-static void center()
-{
- krect.x = rect.width / 2 - krect.width / 2;
- krect.y = rect.height / 2 - krect.height / 2;
-}
-
-/* grabs shortcut on all screens */
-static void grab_shortcut(Shortcut * s)
-{
- XGrabKey(dpy, s->key, s->mod, root,
- True, GrabModeAsync, GrabModeAsync);
- if (num_lock_mask) {
- XGrabKey(dpy, s->key, s->mod | num_lock_mask, root,
- True, GrabModeAsync, GrabModeAsync);
- XGrabKey(dpy, s->key, s->mod | num_lock_mask | LockMask, root,
- True, GrabModeAsync, GrabModeAsync);
- }
- XSync(dpy, False);
-}
-
-/*
- * don't handle evil keys anymore, just define more shortcuts if you cannot
- * live without evil key handling
- */
-static void ungrab_shortcut(Shortcut * s)
-{
- XUngrabKey(dpy, s->key, s->mod, root);
- if (num_lock_mask) {
- XUngrabKey(dpy, s->key, s->mod | num_lock_mask, root);
- XUngrabKey(dpy, s->key, s->mod | num_lock_mask | LockMask, root);
- }
- XSync(dpy, False);
-}
-
-static void create_shortcut(File * f)
-{
- static char *chain[8];
- char *k;
- size_t i, toks;
- Shortcut *s = 0, *r = 0;
-
- cext_strlcpy(buf, f->name, sizeof(buf));
- toks = cext_tokenize(chain, 8, buf, ',');
-
- for (i = 0; i < toks; i++) {
- if (!s)
- r = s = cext_emallocz(sizeof(Shortcut));
- else {
- s->next = cext_emallocz(sizeof(Shortcut));
- s = s->next;
- }
- cext_strlcpy(s->name, chain[i], MAX_BUF);
- k = strrchr(chain[i], '-');
- if (k)
- k++;
- else
- k = chain[i];
- s->key = XKeysymToKeycode(dpy, XStringToKeysym(k));
- s->mod = blitz_strtomod(chain[i]);
- }
- if (r) {
- s->cmdfile = f;
- cext_attach_item(&shortcuts, r);
- grab_shortcut(r);
- }
-}
-
-static void destroy_shortcut(Shortcut * s, int ungrab)
-{
- if (s->next)
- destroy_shortcut(s->next, 0);
- if (ungrab)
- ungrab_shortcut(s);
- free(s);
-}
-
-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 void handle_shortcut_chain(Window w, Shortcut * processed, char *prefix, int grab)
-{
- unsigned long mod;
- KeyCode key;
- Shortcut *s = processed->next;
-
- if (grab) {
- XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
- XMapRaised(dpy, win);
- }
- draw_shortcut_box(prefix);
- next_keystroke(&mod, &key);
-
- if ((processed->mod == mod) && (processed->key == key)) {
- /* double shortcut */
- emulate_key_press(mod, key);
- } else if ((s->mod == mod) && (s->key == key)) {
- if (s->cmdfile && s->cmdfile->content)
- spawn(dpy, s->cmdfile->content);
- else if (s->next) {
- snprintf(buf, sizeof(buf), "%s/%s", prefix, s->name);
- handle_shortcut_chain(w, s, buf, 0);
- }
- }
- if (grab) {
- XUngrabKeyboard(dpy, CurrentTime);
- XUnmapWindow(dpy, win);
- XSync(dpy, False);
- }
-}
-
-static int comp_shortcut(void *comp_short, void *shortcut)
-{
- Shortcut *comp = comp_short;
- Shortcut *s = shortcut;
- return (s->mod == comp->mod) && (s->key == comp->key);
-}
-
-static void handle_shortcut_gkb(Window w, unsigned long mod, KeyCode key)
-{
- Shortcut comp, *s;
- if (!files[K_LOOKUP]->content)
- return;
-
- comp.mod = mod;
- comp.key = key;
-
- s = cext_find_item(&shortcuts, &comp, comp_shortcut);
- if (s && s->cmdfile && s->cmdfile->content) {
- spawn(dpy, s->cmdfile->content);
- return;
- }
- XBell(dpy, 0);
-}
-
-static void handle_shortcut(Window w, unsigned long mod, KeyCode key)
-{
- Shortcut comp, *s;
- if (!files[K_LOOKUP]->content)
- return;
-
- comp.mod = mod;
- comp.key = key;
-
- s = cext_find_item(&shortcuts, &comp, comp_shortcut);
- if (s && s->cmdfile && s->cmdfile->content) {
- spawn(dpy, s->cmdfile->content);
- return;
- }
- if (s && s->next)
- handle_shortcut_chain(w, s, s->name, 1);
-}
-
-static void quit(void *obj, char *arg)
-{
- ixps->runlevel = SHUTDOWN;
-}
-
-static void update()
-{
- Shortcut *s;
- File *f, *p;
- if (!files[K_LOOKUP]->content)
- return;
-
- f = ixp_walk(ixps, files[K_LOOKUP]->content);
-
- if (!f || !is_directory(f))
- return; /* cannot update */
-
- /* destroy existing shortcuts if any */
- while ((s = cext_stack_get_top_item(&shortcuts))) {
- cext_detach_item(&shortcuts, s);
- destroy_shortcut(s, 1);
- }
-
- if (grabkb) {
- XGrabKeyboard(dpy, root, True, GrabModeAsync,
- GrabModeAsync, CurrentTime);
- return;
- }
- /* create new shortcuts */
- for (p = f->content; p; p = p->next)
- create_shortcut(p);
-}
-
-/*
- * Function assumes following fs-structure:
- *
- * /box/style/font "<value>"
- * /box/style/fgcolor "#RRGGBBAA"
- * /box/style/bgcolor "#RRGGBBAA"
- * /box/style/bordercolor "#RRGGBBAA"
- */
-static void draw_shortcut_box(char *text)
-{
- Draw d = { 0 };
-
- d.font = font;
- krect.width = XTextWidth(d.font, text, strlen(text)) + krect.height;
- krect.height = font->ascent + font->descent + 4;
- center();
- XMoveResizeWindow(dpy, win, krect.x, krect.y, krect.width, krect.height);
-
- /* default stuff */
- d.gc = gc;
- d.drawable = win;
- d.data = text;
- d.rect.y = 0;
- d.rect.width = krect.width;
- d.rect.height = krect.height;
- d.bg = blitz_loadcolor(dpy, screen_num, files[K_BG_COLOR]->content);
- d.fg = blitz_loadcolor(dpy, screen_num, files[K_FG_COLOR]->content);
- d.border = blitz_loadcolor(dpy, screen_num, files[K_BORDER_COLOR]->content);
- blitz_drawlabel(dpy, &d);
-}
-
-static void check_event(Connection * c)
-{
- XEvent ev;
-
- while (XPending(dpy)) {
- XNextEvent(dpy, &ev);
- switch (ev.type) {
- case KeyPress:
- ev.xkey.state &= valid_mask;
- if (grabkb)
- handle_shortcut_gkb(root, ev.xkey.state,
- (KeyCode) ev.xkey.keycode);
- else
- handle_shortcut(root, ev.xkey.state,
- (KeyCode) ev.xkey.keycode);
- break;
- case KeymapNotify:
- update();
- break;
- default:
- break;
- }
- }
-}
-
-static void handle_after_write(IXPServer * s, File * f)
-{
- int i;
- size_t len;
-
- if (f == files[K_CTL]) {
- for (i = 0; acttbl[i].name; i++) {
- len = strlen(acttbl[i].name);
- if (!strncmp(acttbl[i].name, (char *) f->content, len)) {
- if (strlen(f->content) > len) {
- acttbl[i].func(0, &((char *) f->content)[len + 1]);
- } else {
- acttbl[i].func(0, 0);
- }
- break;
- }
- }
- } else if (f == files[K_GRAB_KB]) {
- grabkb = blitz_strtonum(files[K_GRAB_KB]->content, 0, 1);
- if (!grabkb) {
- XUngrabKeyboard(dpy, CurrentTime);
- XUnmapWindow(dpy, win);
- XSync(dpy, False);
- } else
- update();
- } else if (f == files[K_FONT]) {
- XFreeFont(dpy, font);
- font = blitz_getfont(dpy, files[K_FONT]->content);
- krect = rect;
- krect.height = font->ascent + font->descent + 4;
- center();
- XMoveResizeWindow(dpy, win, krect.x, krect.y, krect.width, krect.height);
- } else if (f == files[K_LOOKUP]) {
- update();
- }
- check_event(0);
-}
-
-static int dummy_error_handler(Display * dpy, XErrorEvent * err)
-{
- return 0;
-}
-
-int main(int argc, char *argv[])
-{
- int i;
- XSetWindowAttributes wa;
- XGCValues gcv;
-
- /* command line args */
- for (i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
- switch (argv[i][1]) {
- case 'v':
- fprintf(stdout, "%s", version[0]);
- exit(0);
- break;
- case 's':
- if (i + 1 < argc)
- sockfile = argv[++i];
- else
- usage();
- break;
- default:
- usage();
- break;
- }
- }
-
- dpy = XOpenDisplay(0);
- if (!dpy) {
- fprintf(stderr, "%s", "wmikeys: cannot open display\n");
- exit(1);
- }
- XSetErrorHandler(dummy_error_handler);
- screen_num = DefaultScreen(dpy);
-
- /* init */
- ixps = wmii_setup_server(sockfile);
-
- if (!(files[K_CTL] = ixp_create(ixps, "/ctl"))) {
- perror("wmikeys: cannot connect IXP server");
- exit(1);
- }
- files[K_CTL]->after_write = handle_after_write;
- files[K_LOOKUP] = ixp_create(ixps, "/lookup");
- files[K_LOOKUP]->after_write = handle_after_write;
- files[K_GRAB_KB] = wmii_create_ixpfile(ixps, "/grabkeyb", "0");
- files[K_GRAB_KB]->after_write = handle_after_write;
- files[K_FONT] = wmii_create_ixpfile(ixps, "/box/font", BLITZ_FONT);
- files[K_FONT]->after_write = handle_after_write;
- font = blitz_getfont(dpy, files[K_FONT]->content);
- files[K_FG_COLOR] = wmii_create_ixpfile(ixps, "/box/fgcolor", BLITZ_SEL_FG_COLOR);
- files[K_BG_COLOR] = wmii_create_ixpfile(ixps, "/box/bgcolor", BLITZ_SEL_BG_COLOR);
- files[K_BORDER_COLOR] = wmii_create_ixpfile(ixps, "/box/bordercolor", BLITZ_SEL_BORDER_COLOR);
-
- wa.override_redirect = 1;
- wa.background_pixmap = ParentRelative;
- wa.event_mask =
- ExposureMask | SubstructureRedirectMask | SubstructureNotifyMask;
-
- root = RootWindow(dpy, screen_num);
- rect.x = rect.y = 0;
- rect.width = DisplayWidth(dpy, screen_num);
- rect.height = DisplayHeight(dpy, screen_num);
- krect.x = krect.y = 0;
- krect.width = krect.height = 1;
-
- init_lock_modifiers(dpy, &valid_mask, &num_lock_mask);
-
- win = XCreateWindow(dpy, RootWindow(dpy, screen_num), krect.x, krect.y,
- krect.width, krect.height, 0, DefaultDepth(dpy, screen_num),
- CopyFromParent, DefaultVisual(dpy, screen_num),
- CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
- XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_left_ptr));
- XSync(dpy, False);
-
- gcv.function = GXcopy;
- gcv.graphics_exposures = False;
-
- gc = XCreateGC(dpy, win, 0, 0);
-
- /* main event loop */
- run_server_with_fd_support(ixps, ConnectionNumber(dpy),
- check_event, 0);
- deinit_server(ixps);
- XFreeGC(dpy, gc);
- XCloseDisplay(dpy);
-
- return 0;
-}
diff --git a/cmd/wmimenu.1 b/cmd/wmimenu.1
@@ -1,42 +0,0 @@
-.TH WMIMENU 1 wmii-3
-.SH NAME
-wmimenu \- window manager improved 2 menu
-.SH SYNOPSIS
-.B wmimenu
-.B \-s
-.I socketfile
-.SH DESCRIPTION
-.SS Overview
-.B wmimenu
-is a generic, highly customizable, and efficient menu for the X Window System,
-originally designed for
-.BR wmii (1).
-It supports arbitrary, user defined menu contents, which get executed.
-Like wmii,
-.B wmimenu
-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 wmimenu
-should create.
-.TP
-.B \-v
-prints version information to stderr, then exits.
-.SS Customization
-.B wmimenu
-is customized through manipulating its filesystem namespace.
-In the default setup of
-.BR wmii (1)
-the namespace of
-.B wmimenu
-can be found in /menu.
-.SH SEE ALSO
-.BR wmibar (1),
-.BR wmifs (1),
-.BR wmii (1),
-.BR wmiiwm (1),
-.BR wmikeys (1),
-.BR wmir (1)
diff --git a/cmd/wmimenu.c b/cmd/wmimenu.c
@@ -1,621 +0,0 @@
-/*
- * (C)opyright MMIV-MMV Anselm R. Garbe <garbeam at gmail dot com>
- * See LICENSE file for license details.
- */
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <time.h>
-#include <X11/Xatom.h>
-#include <X11/cursorfont.h>
-#include <X11/Xproto.h>
-#include <X11/Xutil.h>
-#include <X11/keysym.h>
-
-#include "wmii.h"
-
-/* array indexes for file pointers */
-typedef enum {
- M_CTL,
- M_GEOMETRY,
- M_PRE_COMMAND,
- M_COMMAND,
- M_HISTORY,
- M_LOOKUP,
- M_FONT,
- M_SEL_BG_COLOR,
- M_SEL_TEXT_COLOR,
- M_SEL_BORDER_COLOR,
- M_NORM_BG_COLOR,
- M_NORM_TEXT_COLOR,
- M_NORM_BORDER_COLOR,
- M_LAST
-} InputIndexes;
-
-enum {
- OFF_NEXT, OFF_PREV, OFF_CURR, OFF_LAST
-};
-
-static IXPServer *ixps = 0;
-static Display *dpy;
-static GC gc;
-static Window win;
-static XRectangle rect;
-static XRectangle mrect;
-static int screen_num;
-static char *sockfile = 0;
-static File *files[M_LAST];
-static Container items = {0};
-static Container history = {0};
-static int offset[OFF_LAST];
-static unsigned int cmdw = 0;
-static Pixmap pmap;
-static const int seek = 30; /* 30px */
-static XFontStruct *font;
-static unsigned int sel = 0;
-static Align align = SOUTH;
-
-static void check_event(Connection * c);
-static void draw_menu(void);
-static void handle_kpress(XKeyEvent * e);
-static void set_text(char *text);
-static void quit(void *obj, char *arg);
-static void display(void *obj, char *arg);
-static int update_items(char *prefix);
-
-static Action acttbl[2] = {
- {"quit", quit},
- {"display", display}
-};
-
-static char *version[] = {
- "wmimenu - window manager improved menu - " VERSION "\n"
- " (C)opyright MMIV-MMV Anselm R. Garbe\n", 0
-};
-
-static void usage()
-{
- fprintf(stderr, "%s",
- "usage: wmimenu [-s <socket file>] [-r] [-v]\n"
- " -s socket file (default: /tmp/.ixp-$USER/wmimenu-%s-%s)\n"
- " -v version info\n");
- exit(1);
-}
-
-static void add_history(char *cmd)
-{
- char buf[MAX_BUF];
- snprintf(buf, MAX_BUF, "/history/%ld", (long) time(0));
- cext_attach_item(&history, wmii_create_ixpfile(ixps, buf, cmd));
-}
-
-static void exec_item(char *cmd)
-{
- File *item = cext_list_get_item(&items, sel);
- char *rc = cmd;
-
- if (!cmd || cmd[0] == 0)
- return;
-
- if (item && item->size)
- rc = cmd = item->content;
- add_history(cmd);
-
- if (files[M_PRE_COMMAND]->content) {
- size_t len = strlen(cmd) + files[M_PRE_COMMAND]->size + 2;
- rc = cext_emallocz(len);
- snprintf(rc, len, "%s %s", (char *) files[M_PRE_COMMAND]->content, cmd);
- }
- /* fallback */
- spawn(dpy, rc);
- /* cleanup */
- if (files[M_PRE_COMMAND]->content)
- free(rc);
-}
-
-static void quit(void *obj, char *arg)
-{
- ixps->runlevel = SHUTDOWN;
-}
-
-static void show()
-{
- set_text(0);
- XMapRaised(dpy, win);
- XSync(dpy, False);
- update_items(files[M_COMMAND]->content);
- draw_menu();
- while (XGrabKeyboard
- (dpy, RootWindow(dpy, screen_num), True, GrabModeAsync,
- GrabModeAsync, CurrentTime) != GrabSuccess)
- usleep(1000);
-}
-
-static void hide()
-{
- XUngrabKeyboard(dpy, CurrentTime);
- XUnmapWindow(dpy, win);
- XSync(dpy, False);
-}
-
-static void display(void *obj, char *arg)
-{
- if (!arg)
- return;
- if (blitz_strtonum(arg, 0, 1))
- show();
- else
- hide();
- check_event(0);
-}
-
-void set_text(char *text)
-{
- if (files[M_COMMAND]->content) {
- free(files[M_COMMAND]->content);
- files[M_COMMAND]->content = 0;
- files[M_COMMAND]->size = 0;
- }
- if (text && strlen(text)) {
- files[M_COMMAND]->content = strdup(text);
- files[M_COMMAND]->size = strlen(text);
- }
-}
-
-static void update_offsets()
-{
- File *item;
- unsigned int i, w = cmdw + 2 * seek;
-
- if (!cext_stack_get_top_item(&items))
- return;
-
- /* calc next offset */
- for (i = offset[OFF_CURR]; (item = cext_list_get_item(&items, i)); i++) {
- w += XTextWidth(font, item->content, strlen(item->content)) + mrect.height;
- if (w > mrect.width)
- break;
- }
- offset[OFF_NEXT] = i;
-
- w = cmdw + 2 * seek;
- for (i = offset[OFF_CURR] - 1; (i >= 0) && (item = cext_list_get_item(&items, i)); i--) {
- w += XTextWidth(font, item->content, strlen(item->content)) + mrect.height;
- if (w > mrect.width)
- break;
- }
- offset[OFF_PREV] = i + 1;
-}
-
-static int update_items(char *pattern)
-{
- size_t plen = pattern ? strlen(pattern) : 0, len, max = 0, size;
- int matched = pattern ? plen == 0 : 1;
- File *f, *p, *maxitem;
-
- if (!files[M_LOOKUP]->content)
- return 0;
- f = ixp_walk(ixps, files[M_LOOKUP]->content);
- if (!f || !is_directory(f))
- return 0;
-
- cmdw = 0;
- offset[OFF_CURR] = offset[OFF_PREV] = offset[OFF_NEXT] = 0;
- sel = 0;
-
- while ((p = cext_stack_get_top_item(&items)))
- cext_detach_item(&items, p);
-
- /* build new items */
- for (p = f->content; p; p = p->next) {
- len = strlen(p->name);
- if (max < len) {
- maxitem = p;
- max = len;
- }
- }
-
- if (maxitem)
- cmdw = XTextWidth(font, maxitem->name, max) + mrect.height;
-
- for (p = f->content; p; p = p->next) {
- if (matched || !strncmp(pattern, p->name, plen)) {
- cext_attach_item(&items, p);
- p->parent = 0; /* HACK to prevent doubled items */
- }
- }
-
- for (p = f->content; p; p = p->next) {
- if (p->parent && strstr(p->name, pattern))
- cext_attach_item(&items, p);
- else
- p->parent = f; /* restore HACK */
- }
-
- size = cext_sizeof(&items);
- update_offsets();
- return size;
-}
-
-/* creates draw structs for menu mode drawing */
-static void draw_menu()
-{
- Draw d = { 0 };
- unsigned int offx = 0;
- int i = 0;
- File *item = 0, *selitem = cext_list_get_item(&items, sel);
-
- d.gc = gc;
- d.font = font;
- d.drawable = pmap;
- d.rect = mrect;
- d.rect.x = 0;
- d.rect.y = 0;
- d.bg = blitz_loadcolor(dpy, screen_num, files[M_NORM_BG_COLOR]->content);
- d.border = blitz_loadcolor(dpy, screen_num, files[M_NORM_BORDER_COLOR]->content);
- blitz_drawlabelnoborder(dpy, &d);
-
- /* print command */
- d.align = WEST;
- d.font = font;
- d.fg = blitz_loadcolor(dpy, screen_num, files[M_NORM_TEXT_COLOR]->content);
- d.data = files[M_COMMAND]->content;
- if (cmdw && selitem)
- d.rect.width = cmdw;
- offx += d.rect.width;
- blitz_drawlabelnoborder(dpy, &d);
-
- d.align = CENTER;
- if (selitem) {
- d.bg = blitz_loadcolor(dpy, screen_num, files[M_NORM_BG_COLOR]->content);
- d.fg = blitz_loadcolor(dpy, screen_num, files[M_NORM_TEXT_COLOR]->content);
- d.data = offset[OFF_CURR] ? "<" : 0;
- d.rect.x = offx;
- d.rect.width = seek;
- offx += d.rect.width;
- blitz_drawlabelnoborder(dpy, &d);
-
- /* determine maximum items */
- for (i = offset[OFF_CURR]; (item = cext_list_get_item(&items, i)) && (i < offset[OFF_NEXT]); i++) {
- d.data = item->name;
- d.rect.x = offx;
- d.rect.width = XTextWidth(d.font, d.data, strlen(d.data)) + mrect.height;
- offx += d.rect.width;
- /*fprintf(stderr, "%s (%d, %d, %d, %d)\n", item->name, d.rect.x, d.rect.y, d.rect.width, d.rect.height);*/
- if (selitem == item) {
- d.bg = blitz_loadcolor(dpy, screen_num, files[M_SEL_BG_COLOR]->content);
- d.fg = blitz_loadcolor(dpy, screen_num, files[M_SEL_TEXT_COLOR]->content);
- d.border = blitz_loadcolor(dpy, screen_num, files[M_SEL_BORDER_COLOR]-> content);
- blitz_drawlabel(dpy, &d);
- } else {
- d.bg = blitz_loadcolor(dpy, screen_num, files[M_NORM_BG_COLOR]->content);
- d.fg = blitz_loadcolor(dpy, screen_num, files[M_NORM_TEXT_COLOR]->content);
- d.border = blitz_loadcolor(dpy, screen_num, files[M_NORM_BORDER_COLOR]->content);
- blitz_drawlabelnoborder(dpy, &d);
- }
- }
-
- d.bg = blitz_loadcolor(dpy, screen_num, files[M_NORM_BG_COLOR]->content);
- d.fg = blitz_loadcolor(dpy, screen_num, files[M_NORM_TEXT_COLOR]->content);
- d.data = item ? ">" : 0;
- d.rect.x = mrect.width - seek;
- d.rect.width = seek;
- blitz_drawlabelnoborder(dpy, &d);
- }
- XCopyArea(dpy, pmap, win, gc, 0, 0, mrect.width, mrect.height, 0, 0);
- XSync(dpy, False);
-}
-
-static void handle_kpress(XKeyEvent * e)
-{
- KeySym ksym;
- char buf[32];
- int num;
- static char text[4096];
- size_t len = 0, size = cext_sizeof(&items);
- File *selitem = cext_list_get_item(&items, sel);
- File *hist = cext_stack_get_top_item(&history);
-
- text[0] = 0;
- if (files[M_COMMAND]->content) {
- cext_strlcpy(text, files[M_COMMAND]->content, sizeof(text));
- len = strlen(text);
- }
- buf[0] = 0;
- num = XLookupString(e, buf, sizeof(buf), &ksym, 0);
-
- if (IsFunctionKey(ksym) || IsKeypadKey(ksym)
- || IsMiscFunctionKey(ksym) || IsPFKey(ksym)
- || IsPrivateKeypadKey(ksym))
- return;
-
- /* first check if a control mask is omitted */
- if (e->state & ShiftMask) {
- if (ksym == XK_ISO_Left_Tab)
- ksym = XK_Left;
- } else if (e->state & ControlMask) {
- switch (ksym) {
- case XK_E:
- case XK_e:
- ksym = XK_End;
- break;
- case XK_H:
- case XK_h:
- ksym = XK_BackSpace;
- break;
- case XK_J:
- case XK_j:
- ksym = XK_Return;
- break;
- case XK_U:
- case XK_u:
- set_text(0);
- update_items(0);
- draw_menu();
- return;
- break;
- default: /* ignore other control sequences */
- return;
- break;
- }
- }
- switch (ksym) {
- case XK_Left:
- if (!selitem)
- return;
- if (sel > 0) {
- selitem = cext_list_get_item(&items, --sel);
- set_text(selitem->name);
- } else
- return;
- break;
- case XK_Right:
- case XK_Tab:
- if (!selitem)
- return;
- if (sel < size - 1) {
- selitem = cext_list_get_item(&items, ++sel);
- set_text(selitem->name);
- } else
- return;
- break;
- case XK_Down:
- if (hist) {
- set_text(hist->content);
- cext_stack_top_item(&history, cext_list_get_next_item(&items, hist));
- }
- update_items(files[M_COMMAND]->content);
- break;
- case XK_Up:
- if (hist) {
- set_text(hist->content);
- cext_stack_top_item(&history, cext_list_get_prev_item(&items, hist));
- }
- update_items(files[M_COMMAND]->content);
- break;
- case XK_Return:
- if (selitem)
- exec_item(selitem->name);
- else if (text)
- exec_item(text);
- case XK_Escape:
- hide();
- break;
- case XK_BackSpace:
- if (len) {
- size_t i = len;
- if (i) {
- do
- text[--i] = 0;
- while (size && i && size == update_items(text));
- }
- set_text(text);
- update_items(files[M_COMMAND]->content);
- }
- break;
- default:
- if ((num == 1) && !iscntrl((int) buf[0])) {
- buf[num] = 0;
- if (len > 0)
- cext_strlcat(text, buf, sizeof(text));
- else
- cext_strlcpy(text, buf, sizeof(text));
- set_text(text);
- update_items(files[M_COMMAND]->content);
- }
- }
- if (selitem) {
- if (sel < offset[OFF_CURR]) {
- offset[OFF_CURR] = offset[OFF_PREV];
- update_offsets();
- } else if (sel >= offset[OFF_NEXT]) {
- offset[OFF_CURR] = offset[OFF_NEXT];
- update_offsets();
- }
- }
- draw_menu();
-}
-
-static void check_event(Connection * c)
-{
- XEvent ev;
-
- while (XPending(dpy)) {
- XNextEvent(dpy, &ev);
- switch (ev.type) {
- case KeyPress:
- handle_kpress(&ev.xkey);
- break;
- case Expose:
- if (ev.xexpose.count == 0) {
- draw_menu();
- }
- break;
- default:
- break;
- }
- }
-}
-
-static void update_geometry()
-{
- mrect = rect;
- mrect.height = font->ascent + font->descent + 4;
- if (align == SOUTH)
- mrect.y = rect.height - mrect.height;
- XMoveResizeWindow(dpy, win, mrect.x, mrect.y, mrect.width, mrect.height);
- XSync(dpy, False);
- XFreePixmap(dpy, pmap);
- pmap = XCreatePixmap(dpy, win, mrect.width, mrect.height, DefaultDepth(dpy, screen_num));
- XSync(dpy, False);
-}
-
-static void handle_after_write(IXPServer * s, File * f)
-{
- int i;
- size_t len;
-
- if (files[M_CTL] == f) {
- for (i = 0; i < 2; i++) {
- len = strlen(acttbl[i].name);
- if (!strncmp(acttbl[i].name, (char *) f->content, len)) {
- if (strlen(f->content) > len) {
- acttbl[i].func(0, &((char *) f->content)[len + 1]);
- } else {
- acttbl[i].func(0, 0);
- }
- break;
- }
- }
- } else if (files[M_GEOMETRY] == f) {
- if (f->content) {
- if (!strncmp(f->content, "south", 6))
- align = SOUTH;
- else if(!strncmp(f->content, "north", 6))
- align = NORTH;
- update_geometry();
- draw_menu();
- }
- } else if (files[M_FONT] == f) {
- XFreeFont(dpy, font);
- font = blitz_getfont(dpy, files[M_FONT]->content);
- update_geometry();
- draw_menu();
- } else if (files[M_COMMAND] == f) {
- update_items(files[M_COMMAND]->content);
- draw_menu();
- }
- check_event(0);
-}
-
-static void handle_before_read(IXPServer * s, File * f)
-{
- char buf[64];
- if (f != files[M_GEOMETRY])
- return;
- snprintf(buf, sizeof(buf), "%d,%d,%d,%d", mrect.x, mrect.y,
- mrect.width, mrect.height);
- if (f->content)
- free(f->content);
- f->content = strdup(buf);
- f->size = strlen(buf);
-}
-
-int main(int argc, char *argv[])
-{
- int i;
- XSetWindowAttributes wa;
- XGCValues gcv;
-
- /* command line args */
- for (i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
- switch (argv[i][1]) {
- case 'v':
- fprintf(stdout, "%s", version[0]);
- exit(0);
- break;
- case 's':
- if (i + 1 < argc)
- sockfile = argv[++i];
- else
- usage();
- break;
- default:
- usage();
- break;
- }
- }
-
- dpy = XOpenDisplay(0);
- if (!dpy) {
- fprintf(stderr, "%s", "wmimenu: cannot open display\n");
- exit(1);
- }
- screen_num = DefaultScreen(dpy);
-
- ixps = wmii_setup_server(sockfile);
-
- /* init */
- if (!(files[M_CTL] = ixp_create(ixps, "/ctl"))) {
- perror("wmimenu: cannot connect IXP server");
- exit(1);
- }
- files[M_CTL]->after_write = handle_after_write;
- files[M_GEOMETRY] = ixp_create(ixps, "/geometry");
- files[M_GEOMETRY]->before_read = handle_before_read;
- files[M_GEOMETRY]->after_write = handle_after_write;
- files[M_PRE_COMMAND] = ixp_create(ixps, "/precmd");
- files[M_COMMAND] = ixp_create(ixps, "/cmd");
- files[M_COMMAND]->after_write = handle_after_write;
- files[M_HISTORY] = ixp_create(ixps, "/history");
- add_history("");
- files[M_LOOKUP] = ixp_create(ixps, "/lookup");
- files[M_FONT] = wmii_create_ixpfile(ixps, "/font", BLITZ_FONT);
- files[M_FONT]->after_write = handle_after_write;
- font = blitz_getfont(dpy, files[M_FONT]->content);
- files[M_SEL_BG_COLOR] = wmii_create_ixpfile(ixps, "/sstyle/bgcolor", BLITZ_SEL_BG_COLOR);
- files[M_SEL_TEXT_COLOR] = wmii_create_ixpfile(ixps, "/sstyle/fgcolor", BLITZ_SEL_FG_COLOR);
- files[M_SEL_BORDER_COLOR] = wmii_create_ixpfile(ixps, "/sstyle/bordercolor", BLITZ_SEL_BORDER_COLOR);
- files[M_NORM_BG_COLOR] = wmii_create_ixpfile(ixps, "/nstyle/bgcolor", BLITZ_NORM_BG_COLOR);
- files[M_NORM_TEXT_COLOR] = wmii_create_ixpfile(ixps, "/nstyle/fgcolor", BLITZ_NORM_FG_COLOR);
- files[M_NORM_BORDER_COLOR] = wmii_create_ixpfile(ixps, "/nstyle/bordercolor", BLITZ_NORM_BORDER_COLOR);
-
- wa.override_redirect = 1;
- wa.background_pixmap = ParentRelative;
- wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask
- | SubstructureRedirectMask | SubstructureNotifyMask;
-
- rect.x = rect.y = 0;
- rect.width = DisplayWidth(dpy, screen_num);
- rect.height = DisplayHeight(dpy, screen_num);
- mrect = rect;
- mrect.height = font->ascent + font->descent + 4;
- mrect.y = rect.height - mrect.height;
-
- win = XCreateWindow(dpy, RootWindow(dpy, screen_num), mrect.x, mrect.y,
- mrect.width, mrect.height, 0, DefaultDepth(dpy, screen_num),
- CopyFromParent, DefaultVisual(dpy, screen_num),
- CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
- XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_xterm));
- XSync(dpy, False);
-
- /* window pixmap */
- gcv.function = GXcopy;
- gcv.graphics_exposures = False;
-
- gc = XCreateGC(dpy, win, 0, 0);
- pmap = XCreatePixmap(dpy, win, mrect.width, mrect.height, DefaultDepth(dpy, screen_num));
-
- /* main event loop */
- run_server_with_fd_support(ixps, ConnectionNumber(dpy), check_event, 0);
- deinit_server(ixps);
- XFreePixmap(dpy, pmap);
- XFreeGC(dpy, gc);
- XCloseDisplay(dpy);
-
- return 0;
-}
diff --git a/cmd/wmiplumb.c b/cmd/wmiplumb.c
@@ -1,92 +0,0 @@
-/*
- * (C)opyright MMIV-MMV Anselm R. Garbe <garbeam at gmail dot com>
- * See LICENSE file for license details.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-
-static char *version[] = {
- "wmiplumb - window manager improved plumb - " VERSION "\n"
- " (C)opyright MMIV-MMV Anselm R. Garbe\n", 0
-};
-
-static void usage()
-{
- fprintf(stderr, "%s\n",
- "usage: wmiplumb [-v]\n" " -v version info\n");
- exit(1);
-}
-
-static void print_sel(Display * dpy, Window w, XSelectionEvent * e)
-{
- Atom typeret;
- int format;
- unsigned long nitems, bytesleft;
- unsigned char *data;
-
- XGetWindowProperty(dpy, w, e->property, 0L, 4096L, False,
- AnyPropertyType, &typeret, &format,
- &nitems, &bytesleft, &data);
- if (format == 8) {
- int i;
- for (i = 0; i < nitems; i++)
- putchar(data[i]);
- putchar('\n');
- }
- XDeleteProperty(dpy, w, e->property);
-}
-
-int main(int argc, char **argv)
-{
- Display *dpy;
- Atom xa_clip_string;
- Window w;
- XEvent ev;
- int pdone = 0;
-
-
- /* command line args */
- if (argc > 1) {
- if (!strncmp(argv[1], "-v", 3)) {
- fprintf(stdout, "%s", version[0]);
- exit(0);
- } else
- usage();
- }
- dpy = XOpenDisplay(0);
- if (!dpy) {
- fprintf(stderr, "%s", "wmiplumb: cannot open display\n");
- exit(1);
- }
- xa_clip_string = XInternAtom(dpy, "PLUMB_STRING", False);
- w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 10, 10, 200, 200,
- 1, CopyFromParent, CopyFromParent);
- while (1 && !pdone) {
- XConvertSelection(dpy, XA_PRIMARY, XA_STRING, xa_clip_string,
- w, CurrentTime);
- XFlush(dpy);
- XNextEvent(dpy, &ev);
- switch (ev.type) {
- case SelectionNotify:
- if (ev.xselection.property != None)
- print_sel(dpy, w, &ev.xselection);
- else
- putchar('\n');
- XDestroyWindow(dpy, w);
- XCloseDisplay(dpy);
- pdone = 1;
- break;
- default:
- break;
- }
- }
- return 0;
- /*
- * XDestroyWindow(dpy, w); XCloseDisplay(dpy); return 1;
- */
-}
diff --git a/cmd/wmir.1 b/cmd/wmir.1
@@ -1,71 +0,0 @@
-.TH WMIR 1 wmii-3
-.SH NAME
-wmir \- window manager improved 2 remote
-.SH SYNOPSIS
-.B wmir
-.RB [ \-s
-.IR socketfile ]
-.I action
-.I action_arg
-[...]
-.br
-.B wmir
-.RB [ \-s
-.IR socketfile ]
-.B \-f
-.br
-.B wmir
-.B \-v
-.SH DESCRIPTION
-.SS Overview
-.B wmir
-is a client to access wmi* fileservers for the command line and
-scripts. It can be used to configure wmii(1).
-.SS Options
-.TP
-.BI \-s " socketfile"
-lets you specify the socketfile to which
-.B wmir
-a connection will be established. If the environment variable
-.B WMIR_SOCKET
-is set and points to a socket file, wmir will use that file, if this
-option is not supplied.
-.TP
-.B \-f
-reads from stdin, useful for interactive wmir sessions or for
-scripts that write/read a bunch of data, because this speeds things up
-due to missing process creation/destruction, ie., a hack.
-.TP
-.B \-v
-prints version information to stderr, then exits.
-.TP
-The syntax of the actions is as follows:
-.TP
-.B create <path/file> [<value>]
-creates file
-.TP
-.B write <file> <value>
-writes value to a file
-.TP
-.B read <path/file>
-reads file or directory contents
-.TP
-.B remove <path/file>
-removes file or directory tree
-.SH ENVIRONMENT
-.TP
-WMIR_SOCKET
-See above.
-.SH EXAMPLES
-.TP
-$ wmir read /
-This gives you an idea about what the wmii filesystem currently looks like.
-.TP
-$ wmir write /wm/ctl quit
-.SH SEE ALSO
-.BR wmibar (1),
-.BR wmifs (1),
-.BR wmii (1),
-.BR wmiiwm (1),
-.BR wmikeys (1),
-.BR wmimenu (1)
diff --git a/cmd/wmir.c b/cmd/wmir.c
@@ -1,225 +0,0 @@
-/*
- * (C)opyright MMIV-MMV Anselm R. Garbe <garbeam at gmail dot com>
- * See LICENSE file for license details.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "ixp.h"
-
-static IXPClient *c;
-static int exit_code = 0;
-
-static char *version[] = {
- "wmir - window manager improved remote - " VERSION "\n"
- " (C)opyright MMIV-MMV Anselm R. Garbe\n", 0
-};
-
-static void usage()
-{
- fprintf(stderr, "%s",
- "usage: wmir [-s <socket file>] [-v] <action> <action_arg> [...]\n"
- " -s socket file (default: $WMIR_SOCKET)\n"
- " -f read actions from stdin\n"
- " -v version info\n"
- "actions:\n"
- " create <file> [<content>] -- creates and optionally writes content to a file\n"
- " write <file> <content> -- writes content to a file\n"
- " read <directory/file> -- reads file or directory contents\n"
- " remove <directory/file> -- removes file or directory, use with care!\n");
- exit(1);
-}
-
-static void perform(char *action, char *file, char *content)
-{
- size_t out_len = 0;
- char output[2050];
- int crt, fd = -1;
-
- if (!action)
- return;
-
- crt = !strncmp(action, "create", 7);
- if (!strncmp(action, "write", 6) || crt) {
- if (!file)
- return;
- /* create file first */
- if (crt) {
- c->create(c, file);
- if (c->errstr) {
- fprintf(stderr, "wmir: error: create %s: %s\n", file,
- c->errstr);
- exit_code = 1;
- return;
- }
- }
- if (!content)
- return;
- fd = c->open(c, file);
- if (c->errstr) {
- fprintf(stderr, "wmir: error: open %s: %s\n", file, c->errstr);
- exit_code = 1;
- return;
- }
- c->write(c, fd, content, strlen(content));
- if (c->errstr) {
- fprintf(stderr, "wmir: error: write %s: %s\n", file,
- c->errstr);
- exit_code = 1;
- if (!strncmp(c->errstr, DEAD_SERVER, strlen(DEAD_SERVER) + 1))
- return;
- }
- } else if (!strncmp(action, "read", 5)) {
- if (!file)
- return;
- fd = c->open(c, file);
- if (c->errstr) {
- fprintf(stderr, "wmir: error: open %s: %s\n", file, c->errstr);
- exit_code = 1;
- return;
- }
- do {
- out_len = c->read(c, fd, output, 2048);
- if (c->errstr) {
- fprintf(stderr, "wmir: error: read %s: %s\n", file,
- c->errstr);
- exit_code = 1;
- if (!strncmp
- (c->errstr, DEAD_SERVER, strlen(DEAD_SERVER) + 1))
- return;
- break;
- }
- output[out_len] = 0;
- fprintf(stdout, "%s", output);
- }
- while (out_len == 2048);
- fprintf(stdout, "%s", "\n");
- } else if (!strncmp(action, "remove", 7)) {
- if (!file)
- return;
- c->remove(c, file);
- if (c->errstr) {
- fprintf(stderr, "wmir: error: remove %s: %s\n", file,
- c->errstr);
- exit_code = 1;
- return;
- }
- }
- if (fd != -1) {
- c->close(c, fd);
- if (c->errstr) {
- fprintf(stderr, "wmir: error: close %s: %s\n", file,
- c->errstr);
- exit_code = 1;
- return;
- }
- }
-}
-
-int main(int argc, char *argv[])
-{
- int i = 0, read_stdin = 0;
- char line[4096], *p;
- char *sockfile = getenv("WMIR_SOCKET");
-
- /* command line args */
- if (argc > 1) {
- for (i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
- switch (argv[i][1]) {
- case 'v':
- fprintf(stderr, "%s", version[0]);
- exit(0);
- break;
- case 's':
- if (i + 1 < argc) {
- sockfile = argv[++i];
- } else {
- usage();
- }
- break;
- case 'f':
- read_stdin = 1;
- break;
- default:
- usage();
- break;
- }
- }
- }
- if ((argc <= 1) || (!read_stdin && (i + 1) >= argc)) {
- fprintf(stderr, "%s", "wmir: arguments: ");
- for (i = 1; i < argc; i++)
- fprintf(stderr, "%s, ", argv[i]);
- fprintf(stderr, "%s", "\n");
- usage();
- }
- if (!sockfile) {
- fprintf(stderr, "%s",
- "wmir: error: WMIR_SOCKET environment not set\n");
- usage();
- }
- /* open socket */
- if (!(c = init_ixp_client(sockfile))) {
- fprintf(stderr, "wmir: cannot connect to server '%s'\n", sockfile);
- exit(1);
- }
- if (read_stdin) {
- /* simple shell */
- char *action, *file, *content;
- while (fgets(line, 4096, stdin)) {
- p = line;
- while (*p != 0 && (*p == ' ' || *p == '\t'))
- p++;
- if (*p == 0)
- continue; /* empty line */
- if (strncmp(p, "create ", 7) &&
- strncmp(p, "write ", 6) &&
- strncmp(p, "read ", 5) && strncmp(p, "remove ", 7))
- continue;
-
- action = p;
- while (*p != 0 && *p != ' ' && *p != '\t' && *p != '\n')
- p++;
- if (*p == 0 || *p == '\n')
- continue; /* ignore bogus command */
- *p = 0;
- p++;
- while (*p != 0 && (*p == ' ' || *p == '\t'))
- p++;
- if (*p == 0)
- continue; /* ignore bogus command */
- file = p;
- while (*p != 0 && *p != ' ' && *p != '\t' && *p != '\n')
- p++;
- if (*p == 0 || *p == '\n') {
- content = 0;
- *p = 0;
- } else {
- *p = 0;
- p++;
- content = p;
- }
- if (file[0] == 0)
- continue;
- if (content) {
- static size_t len;
- if ((len = strlen(content)))
- content[len - 1] = 0;
- }
- perform(action, file, content);
- if (c->errstr)
- fprintf(stderr, "wmir: error: read %s: %s\n", file,
- c->errstr);
- }
- } else {
- perform(argv[i], argv[i + 1], (i + 2) < argc ? argv[i + 2] : 0);
- }
-
- if (c->errstr) {
- deinit_client(c);
- exit_code = 1;
- }
- return exit_code;
-}
diff --git a/cmd/wmir2.c b/cmd/wmir2.c
@@ -1,243 +0,0 @@
-/*
- * (C)opyright MMIV-MMV Anselm R. Garbe <garbeam at gmail dot com>
- * See LICENSE file for license details.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../libixp2/ixp.h"
-
-#include <cext.h>
-
-typedef struct {
- char *name;
- int (*cmd) (char **argv);
- int min_argc;
-} Command;
-
-static int xcreate(char **argv);
-static int xread(char **argv);
-static int xwrite(char **argv);
-static int xremove(char **argv);
-static Command cmds[] = {
- {"create", xcreate, 2},
- {"read", xread, 1},
- {"write", xwrite, 2},
- {"remove", xremove, 1},
- {0, 0}
-};
-static IXPClient c = { 0 };
-
-static char *version[] = {
- "wmir - window manager improved remote - " VERSION "\n"
- " (C)opyright MMIV-MMV Anselm R. Garbe\n", 0
-};
-
-static void usage()
-{
- fprintf(stderr, "%s",
- "usage: wmir [-s <socket file>] [-v] <command> <args> [...]\n"
- " -s socket file (default: $WMIR_SOCKET)\n"
- " -f read commands from stdin\n"
- " -v version info\n"
- "commands:\n"
- " create <file> <content> -- creates file\n"
- " read <file/directory> -- reads file/directory contents\n"
- " write <file> <content> -- writes content to a file\n"
- " remove <file/directory> -- removes file\n");
- exit(1);
-}
-
-static u32 write_data(u32 fid, u8 * data, u32 count)
-{
- u32 len, i, runs = count / c.fcall.iounit;
-
- for (i = 0; i <= runs; i++) {
- /* write */
- len = count - (i * c.fcall.iounit);
- if (len > c.fcall.iounit)
- len = c.fcall.iounit;
- if (ixp_client_write
- (&c, fid, i * c.fcall.iounit, len,
- &data[i * c.fcall.iounit]) != count) {
- fprintf(stderr, "wmir: cannot write file: %s\n", c.errstr);
- return 0;
- }
- }
- return count;
-}
-
-static int xcreate(char **argv)
-{
- u32 fid;
- char *p = strrchr(argv[0], '/');
-
- fid = c.root_fid << 2;
- /* walk to bottom-most directory */
- *p = 0;
- if (!ixp_client_walk(&c, fid, argv[0])) {
- fprintf(stderr, "wmir: cannot walk to %s: %s\n", argv[0],
- c.errstr);
- return 1;
- }
- /* create */
- p++;
- if (!ixp_client_create(&c, fid, p, (u32) 0xff, IXP_OWRITE)) {
- fprintf(stderr, "wmir: cannot create file: %s\n", c.errstr);
- return 1;
- }
- write_data(fid, (u8 *) argv[1], strlen(argv[1]));
- return !ixp_client_close(&c, fid);
-}
-
-static int xwrite(char **argv)
-{
- /* open */
- u32 fid = c.root_fid << 2;
- if (!ixp_client_open(&c, fid, argv[0], IXP_OWRITE)) {
- fprintf(stderr, "wmir: cannot open file: %s\n", c.errstr);
- return 1;
- }
- write_data(fid, (u8 *) argv[1], strlen(argv[1]));
- return !ixp_client_close(&c, fid);
-}
-
-static void print_directory(void *result, u32 msize)
-{
- void *p = result;
- static Stat stat, zerostat = { 0 };
- u32 len = 0;
- do {
- p = ixp_dec_stat(p, &stat);
- len += stat.size + sizeof(u16);
- if (stat.qid.type == IXP_QTDIR)
- fprintf(stdout, "%s/\n", stat.name);
- else
- fprintf(stdout, "%s\n", stat.name);
- stat = zerostat;
- }
- while (len < msize);
-}
-
-static int xread(char **argv)
-{
- u32 count, fid = c.root_fid << 2;
- int is_directory = FALSE;
- static u8 result[IXP_MAX_MSG];
-
- /* open */
- if (!ixp_client_open(&c, fid, argv[0], IXP_OREAD)) {
- fprintf(stderr, "wmir: cannot open file: %s\n", c.errstr);
- return 1;
- }
- is_directory = !c.fcall.nwqid || (c.fcall.qid.type == IXP_QTDIR);
- /* read */
- if (!(count = ixp_client_read(&c, fid, 0, result, IXP_MAX_MSG))
- && c.errstr) {
- fprintf(stderr, "wmir: cannot read file: %s\n", c.errstr);
- return 1;
- }
- if (count) {
- if (is_directory)
- print_directory(result, count);
- else {
- u32 i;
- for (i = 0; i < count; i++)
- putchar(result[i]);
- }
- }
- return !ixp_client_close(&c, fid);
-}
-
-static int xremove(char **argv)
-{
- u32 fid;
-
- /* remove */
- fid = c.root_fid << 2;
- if (!ixp_client_remove(&c, fid, argv[0])) {
- fprintf(stderr, "wmir: cannot remove file: %s\n", c.errstr);
- return 1;
- }
- return 0;
-}
-
-static int perform_cmd(int argc, char **argv)
-{
- int i;
- for (i = 0; cmds[i].name; i++)
- if (!strncmp(cmds[i].name, argv[0], strlen(cmds[i].name))) {
- if (cmds[i].min_argc <= argc)
- return cmds[i].cmd(&argv[1]);
- else
- usage();
- }
- /* bogus command */
- return 1;
-}
-
-int main(int argc, char *argv[])
-{
- int i = 0, ret, read_stdin = 0;
- char line[4096];
- char *sockfile = getenv("WMIR_SOCKET");
-
- /* command line args */
- if (argc > 1) {
- for (i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
- switch (argv[i][1]) {
- case 'v':
- fprintf(stderr, "%s", version[0]);
- exit(0);
- break;
- case 's':
- if (i + 1 < argc)
- sockfile = argv[++i];
- else
- usage();
- break;
- case 'f':
- read_stdin = 1;
- break;
- default:
- usage();
- break;
- }
- }
- }
- if ((argc <= 1) || (!read_stdin && (i + 1) >= argc)) {
- fprintf(stderr, "%s", "wmir: arguments: ");
- for (i = 1; i < argc; i++)
- fprintf(stderr, "%s, ", argv[i]);
- fprintf(stderr, "%s", "\n");
- usage();
- }
- if (!sockfile) {
- fprintf(stderr, "%s",
- "wmir: error: WMIR_SOCKET environment not set\n");
- usage();
- }
- /* open socket */
- if (!ixp_client_init(&c, sockfile)) {
- fprintf(stderr, "wmir: %s\n", c.errstr);
- exit(1);
- }
- /* wether perform directly or read from stdin */
- if (read_stdin) {
- char *_argv[3];
- int _argc;
- while (fgets(line, 4096, stdin))
- if ((_argc = cext_tokenize(_argv, 3, line, ' '))) {
- if ((ret = perform_cmd(_argc, _argv)))
- break;
- }
- } else
- ret = perform_cmd(argc - (i + 1), &argv[i]);
-
- /* close socket */
- ixp_client_deinit(&c);
-
- return ret;
-}
diff --git a/cmd/wmiwarp.c b/cmd/wmiwarp.c
@@ -1,54 +0,0 @@
-/*
- * (C)opyright MMIV-MMV Anselm R. Garbe <garbeam at gmail dot com>
- * See LICENSE file for license details.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-
-static char *version[] = {
- "wmiwarp - window manager improved warp - " VERSION "\n"
- " (C)opyright MMIV-MMV Anselm R. Garbe\n", 0
-};
-
-static void usage()
-{
- fprintf(stderr,
- "usage: wmiwarp [-v] <x>,<y>\n" " -v version info\n");
- exit(1);
-}
-
-int main(int argc, char **argv)
-{
- Display *dpy;
- int x, y;
-
- /* command line args */
- if (argc != 2)
- usage();
- if (!strncmp(argv[1], "-v", 2)) {
- fprintf(stdout, "%s", version[0]);
- exit(0);
- }
- dpy = XOpenDisplay(0);
- if (!dpy) {
- fprintf(stderr, "%s", "wmiwarp: cannot open display\n");
- exit(1);
- }
- if (!strncmp(argv[1], "center", 7)) {
- x = DisplayWidth(dpy, DefaultScreen(dpy)) / 2;
- y = DisplayHeight(dpy, DefaultScreen(dpy)) / 2;
- } else if (sscanf(argv[1], "%d,%d", &x, &y) != 2) {
- XCloseDisplay(dpy);
- usage();
- }
- XWarpPointer(dpy, None, RootWindow(dpy, DefaultScreen(dpy)),
- 0, 0, 0, 0, x, y);
- XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
- XCloseDisplay(dpy);
- return 0;
-}
diff --git a/rc/kmode b/rc/kmode
@@ -1,11 +1,11 @@
#!9PREFIX/bin/rc
# activate shortcuts of the given mode
-wmir write /keys/grabkeyb 0
-wmir write /keys/lookup /mode/$1
+wmiir write /keys/grabkeyb 0
+wmiir write /keys/lookup /mode/$1
-plab_cmd=`{wmir read /wm/event/pageupdate | sed -e 's/\\//'}
+plab_cmd=`{wmiir read /wm/event/pageupdate | sed -e 's/\\//'}
if (! ~ $#plab_cmd 0) eval $"plab_cmd
-#wmir write /bar/$plab/data \
-#`{wmir read /bar/$plab/data | sed -e 's/.$/'^`{echo $2 | cut -b1}^'/'}
+#wmiir write /bar/$plab/data \
+#`{wmiir read /bar/$plab/data | sed -e 's/.$/'^`{echo $2 | cut -b1}^'/'}
diff --git a/rc/quit b/rc/quit
@@ -1,4 +1,4 @@
#!9PREFIX/bin/rc
# quit wmii
-wmir write /wm/ctl quit
+wmiir write /wm/ctl quit
diff --git a/rc/status b/rc/status
@@ -8,22 +8,22 @@ if(test -r $PIDFILE) {
}
echo $pid >$PIDFILE
-label=`{wmir read /bar/new}
-wmir write /bar/$label/b1press 'wmir write /wm/ctl ''select prev'''
-wmir write /bar/$label/b3press 'wmir write /wm/ctl ''select next'''
-wmir write /bar/$label/b4press 'wmir write /wm/ctl ''select prev'''
-wmir write /bar/$label/b5press 'wmir write /wm/ctl ''select next'''
+label=`{wmiir read /bar/new}
+wmiir write /bar/$label/b1press 'wmiir write /wm/ctl ''select prev'''
+wmiir write /bar/$label/b3press 'wmiir write /wm/ctl ''select next'''
+wmiir write /bar/$label/b4press 'wmiir write /wm/ctl ''select prev'''
+wmiir write /bar/$label/b5press 'wmiir write /wm/ctl ''select next'''
# install signal handler for artificial sigexit:
fn sigint {
if(test -f $PIDFILE && ~ `{cat $PIDFILE} $pid)
rm -f $PIDFILE
- wmir write /bar/ctl 'destroy '^$label
+ wmiir write /bar/ctl 'destroy '^$label
exit
}
text=fnord
-while(wmir write /bar/$label/data $"text >[2]/dev/null) {
+while(wmiir write /bar/$label/data $"text >[2]/dev/null) {
# if you need formatted date, use /bin/date instead
text=(`{date} `{uptime | sed 's/.*://; s/,//g'})
sleep 10
diff --git a/rc/welcome b/rc/welcome
@@ -49,13 +49,13 @@ Let's go!
window somewhere to the left. Afterwards, swap them once again, but this
time by pressing M-return.
- We'll now have a look at the internal filesystem used by wmii. Executing
- wmir read /
+ wmiir read /
in the shell of the terminal will list all the files in the root directory.
Files ending with a slash are directories. As you can see, / contains a
"normal" file and four directories. These directories correspond to the
four main components of wmii: wmiiwm, wmibar, wmikeys, and wmimenu. If you
are curious, you can now dig deeper into the directory trees. For instance,
- wmir read /bar/1/b1press
+ wmiir read /bar/1/b1press
will show you which command gets executed when you left-click on the page
label in the bar.
diff --git a/rc/wmiirc b/rc/wmiirc
@@ -0,0 +1,170 @@
+#!9PREFIX/bin/rc
+# configure wmii
+
+TAB=0
+
+SEL_BG_COLOR='#002200'
+SEL_FG_COLOR='#66ff00'
+SEL_BORDER_COLOR='#66ff00'
+NORM_BG_COLOR='#000000'
+NORM_FG_COLOR='#eeeeee'
+NORM_BORDER_COLOR='#111111'
+FONT='-artwiz-snap-normal-*-*-*-*-*-*-*-*-*-*-*'
+
+MODKEY=M
+NORTHKEY=k
+SOUTHKEY=j
+WESTKEY=h
+EASTKEY=l
+
+nl='
+'
+
+fn kbind {
+ wmiir create /keys/mode/$1/$2 $3
+}
+
+fn selstyle {
+ wmiir write $1/fgcolor $SEL_FG_COLOR
+ wmiir write $1/bgcolor $SEL_BG_COLOR
+ wmiir write $1/bordercolor $SEL_BORDER_COLOR
+}
+
+fn normstyle {
+ wmiir write $1/fgcolor $NORM_FG_COLOR
+ wmiir write $1/bgcolor $NORM_BG_COLOR
+ wmiir write $1/bordercolor $NORM_BORDER_COLOR
+}
+
+fn items {
+ ifs=:$nl { dirs=`{echo $2} }
+ {
+ for(dir in $dirs) {
+ for(file in $dir/*) {
+ if(! ~ $file $dir^'/*' && ! test -d $file && test -x $file) {
+ file=`{basename $file}
+ echo create /menu/items/$1/$"file $"file
+ }
+ }
+ }
+ } | sort | wmiir -f &
+}
+
+fn frameconf {
+ wmiir write $1/event/b2press 'wmiir write /wm/ctl close'
+ normstyle $1/nstyle
+ selstyle $1/sstyle
+ wmiir write $1/tab $TAB
+ if(~ $2 refresh)
+ wmiir write $1/geometry +0,+0,+0,+0 # causes refresh
+}
+
+fn framesconf {
+ for(frame in `{wmiir read $1 | grep '^[0-9]'})
+ frameconf $1/$frame $2
+}
+
+
+# WMIBAR CONFIGURATION
+
+fn barsucks {
+ wmiir write /bar/$1/b1press 'wmiir write /wm/ctl ''select prev'''
+ wmiir write /bar/$1/b3press 'wmiir write /wm/ctl ''select next'''
+ wmiir write /bar/$1/b4press 'wmiir write /wm/ctl ''select prev'''
+ wmiir write /bar/$1/b5press 'wmiir write /wm/ctl ''select next'''
+}
+
+wmiir write /bar/ctl reset
+wmiir write /bar/font $FONT
+wmiir write /bar/fgcolor $NORM_FG_COLOR
+wmiir write /bar/bgcolor $NORM_BG_COLOR
+wmiir write /bar/bordercolor $NORM_BORDER_COLOR
+
+plab=`{wmiir read /bar/new}
+wmiir write /bar/$plab/b1press 'wmiir write /wm/ctl pager'
+
+llab=`{wmiir read /bar/new}
+wmiir write /bar/$llab/b1press 'wmiir write /wm/ctl pager'
+
+clab=`{wmiir read /bar/new}
+wmiir write /bar/$clab/fgcolor $SEL_FG_COLOR
+wmiir write /bar/$clab/bgcolor $SEL_BG_COLOR
+wmiir write /bar/$clab/bordercolor $SEL_BG_COLOR
+barsucks $clab
+
+wmiir write /bar/expandable $clab
+wmiir write /bar/ctl 'display 1'
+
+
+# WMIIWM CONFIGURATION
+
+wmiir write /wm/default/font $FONT
+wmiir write /wm/default/transcolor $SEL_BORDER_COLOR
+wmiir write /wm/default/handleinc 0
+
+wmiir write /wm/default/border 1
+wmiir write /wm/event/clientupdate \
+'text=`{wmiir read /wm/sel/layout/sel/frame/sel/client/sel/name} \
+wmiir write /bar/'^$clab^'/data $"text'
+wmiir write /wm/event/pageupdate \
+'wmiir write /bar/'^$plab^'/data `{wmiir read /wm/sel/name} &&' ^ \
+'wmiir write /bar/'^$llab^'/data `{wmiir read /wm/sel/layout/sel/name}'
+
+for(frame in `{wmiir read /wm/sel/layout/sel | grep '^[0-9]'})
+ framesconf /wm/sel/layout/sel/$frame refresh
+frameconf /wm/default norefresh
+
+
+# WMIKEYS CONFIGURATION
+
+kbind bare $MODKEY-Escape 'kmode normal'
+
+kbind normal $MODKEY-C-b 'kmode bare'
+kbind normal $MODKEY-C-a 'wmiir write /menu/precmd ''''; wmiir write /menu/lookup /items/actions; wmiir write /menu/ctl ''display 1'''
+kbind normal $MODKEY-C-p 'wmiir write /menu/precmd extern; wmiir write /menu/lookup /items/programs; wmiir write /menu/ctl ''display 1'''
+kbind normal $MODKEY-C-c 'wmiir write /wm/ctl close'
+kbind normal $MODKEY-C-q,y quit
+kbind normal $MODKEY-C-w,y wmiirc
+kbind normal $MODKEY-t 'extern urxvt ''+sb'' -bg ''#000000'' -fg ''#ffffff'' -cr ''#ffffff'' -sl 4000 -fn -artwiz-smoothansi-*-*-*-*-*-*-*-*-*-*-*-*'
+kbind normal $MODKEY-d 'wmiir write /wm/ctl detach'
+kbind normal $MODKEY-a 'wmiir write /wm/ctl attach'
+kbind normal $MODKEY-S-a 'wmiir write /wm/ctl ''detached clients'''
+kbind normal $MODKEY-S-c 'wmiir write /wm/sel/layout/sel/geometry 0,0,east,south-20; wmiir write /wm/sel/layout/sel/name column'
+kbind normal $MODKEY-S-n 'wmiir write /wm/sel/layout/sel/ctl new'
+kbind normal $MODKEY-S-d 'wmiir write /wm/sel/layout/sel/ctl destroy'
+kbind normal $MODKEY-S-f 'wmiir write /wm/sel/layout/sel/name float'
+kbind normal $MODKEY-Return 'wmiir write /wm/sel/ctl ''select zoomed'''
+kbind normal $MODKEY-C-y 'wmiir write /wm/ctl new'
+kbind normal $MODKEY-u 'wmiir write /wm/sel/layout/sel/frame/sel/locked 0'
+kbind normal $MODKEY-S-u 'wmiir write /wm/sel/layout/sel/frame/sel/locked 1'
+kbind normal $MODKEY-$WESTKEY 'wmiir write /wm/ctl ''select prev'''
+kbind normal $MODKEY-$EASTKEY 'wmiir write /wm/ctl ''select next'''
+kbind normal $MODKEY-Tab 'wmiir write /wm/sel/layout/sel/ctl ''select next'''
+kbind normal $MODKEY-$SOUTHKEY 'wmiir write /wm/sel/layout/sel/ctl ''select next'''
+kbind normal $MODKEY-$NORTHKEY 'wmiir write /wm/sel/layout/sel/ctl ''select prev'''
+kbind normal $MODKEY-S-$WESTKEY 'wmiir write /wm/sel/layout/sel/ctl ''select west'''
+kbind normal $MODKEY-S-$EASTKEY 'wmiir write /wm/sel/layout/sel/ctl ''select east'''
+kbind normal $MODKEY-S-Tab 'wmiir write /wm/sel/layout/sel/frame/sel/ctl ''select next'''
+kbind normal $MODKEY-S-$SOUTHKEY 'wmiir write /wm/sel/layout/sel/frame/sel/ctl ''select next'''
+kbind normal $MODKEY-S-$NORTHKEY 'wmiir write /wm/sel/layout/sel/frame/sel/ctl ''select prev'''
+kbind normal $MODKEY-space 'wmiir write /wm/sel/ctl ''select toggled'''
+kbind normal $MODKEY-S-p 'wmiir write /wm/ctl pager'
+for(i in 0 1 2 3 4 5 6 7 8 9) {
+ kbind normal $MODKEY-S-$i 'wmiir write /wm/ctl ''select '^$i^''''
+}
+
+wmiir write /keys/box/font $FONT
+selstyle /keys/box
+kmode normal
+
+# WMIMENU CONFIGURATION
+items actions $WMII_CONFDIR:$HOME/.wmii-3
+wmiir create /menu/items/actions/rmpage 'wmiir write /wm/ctl destroy'
+items programs $OLD_PATH
+wmiir write /menu/font $FONT
+normstyle /menu/nstyle >[2]/dev/null
+selstyle /menu/sstyle >[2]/dev/null
+
+# MISC
+xsetroot -solid black
+status&
diff --git a/rc/wmirc b/rc/wmirc
@@ -1,170 +0,0 @@
-#!9PREFIX/bin/rc
-# configure wmii
-
-TAB=0
-
-SEL_BG_COLOR='#002200'
-SEL_FG_COLOR='#66ff00'
-SEL_BORDER_COLOR='#66ff00'
-NORM_BG_COLOR='#000000'
-NORM_FG_COLOR='#eeeeee'
-NORM_BORDER_COLOR='#111111'
-FONT='-artwiz-snap-normal-*-*-*-*-*-*-*-*-*-*-*'
-
-MODKEY=M
-NORTHKEY=k
-SOUTHKEY=j
-WESTKEY=h
-EASTKEY=l
-
-nl='
-'
-
-fn kbind {
- wmir create /keys/mode/$1/$2 $3
-}
-
-fn selstyle {
- wmir write $1/fgcolor $SEL_FG_COLOR
- wmir write $1/bgcolor $SEL_BG_COLOR
- wmir write $1/bordercolor $SEL_BORDER_COLOR
-}
-
-fn normstyle {
- wmir write $1/fgcolor $NORM_FG_COLOR
- wmir write $1/bgcolor $NORM_BG_COLOR
- wmir write $1/bordercolor $NORM_BORDER_COLOR
-}
-
-fn items {
- ifs=:$nl { dirs=`{echo $2} }
- {
- for(dir in $dirs) {
- for(file in $dir/*) {
- if(! ~ $file $dir^'/*' && ! test -d $file && test -x $file) {
- file=`{basename $file}
- echo create /menu/items/$1/$"file $"file
- }
- }
- }
- } | sort | wmir -f &
-}
-
-fn frameconf {
- wmir write $1/event/b2press 'wmir write /wm/ctl close'
- normstyle $1/nstyle
- selstyle $1/sstyle
- wmir write $1/tab $TAB
- if(~ $2 refresh)
- wmir write $1/geometry +0,+0,+0,+0 # causes refresh
-}
-
-fn framesconf {
- for(frame in `{wmir read $1 | grep '^[0-9]'})
- frameconf $1/$frame $2
-}
-
-
-# WMIBAR CONFIGURATION
-
-fn barsucks {
- wmir write /bar/$1/b1press 'wmir write /wm/ctl ''select prev'''
- wmir write /bar/$1/b3press 'wmir write /wm/ctl ''select next'''
- wmir write /bar/$1/b4press 'wmir write /wm/ctl ''select prev'''
- wmir write /bar/$1/b5press 'wmir write /wm/ctl ''select next'''
-}
-
-wmir write /bar/ctl reset
-wmir write /bar/font $FONT
-wmir write /bar/fgcolor $NORM_FG_COLOR
-wmir write /bar/bgcolor $NORM_BG_COLOR
-wmir write /bar/bordercolor $NORM_BORDER_COLOR
-
-plab=`{wmir read /bar/new}
-wmir write /bar/$plab/b1press 'wmir write /wm/ctl pager'
-
-llab=`{wmir read /bar/new}
-wmir write /bar/$llab/b1press 'wmir write /wm/ctl pager'
-
-clab=`{wmir read /bar/new}
-wmir write /bar/$clab/fgcolor $SEL_FG_COLOR
-wmir write /bar/$clab/bgcolor $SEL_BG_COLOR
-wmir write /bar/$clab/bordercolor $SEL_BG_COLOR
-barsucks $clab
-
-wmir write /bar/expandable $clab
-wmir write /bar/ctl 'display 1'
-
-
-# WMIIWM CONFIGURATION
-
-wmir write /wm/default/font $FONT
-wmir write /wm/default/transcolor $SEL_BORDER_COLOR
-wmir write /wm/default/handleinc 0
-
-wmir write /wm/default/border 1
-wmir write /wm/event/clientupdate \
-'text=`{wmir read /wm/sel/layout/sel/frame/sel/client/sel/name} \
-wmir write /bar/'^$clab^'/data $"text'
-wmir write /wm/event/pageupdate \
-'wmir write /bar/'^$plab^'/data `{wmir read /wm/sel/name} &&' ^ \
-'wmir write /bar/'^$llab^'/data `{wmir read /wm/sel/layout/sel/name}'
-
-for(frame in `{wmir read /wm/sel/layout/sel | grep '^[0-9]'})
- framesconf /wm/sel/layout/sel/$frame refresh
-frameconf /wm/default norefresh
-
-
-# WMIKEYS CONFIGURATION
-
-kbind bare $MODKEY-Escape 'kmode normal'
-
-kbind normal $MODKEY-C-b 'kmode bare'
-kbind normal $MODKEY-C-a 'wmir write /menu/precmd ''''; wmir write /menu/lookup /items/actions; wmir write /menu/ctl ''display 1'''
-kbind normal $MODKEY-C-p 'wmir write /menu/precmd extern; wmir write /menu/lookup /items/programs; wmir write /menu/ctl ''display 1'''
-kbind normal $MODKEY-C-c 'wmir write /wm/ctl close'
-kbind normal $MODKEY-C-q,y quit
-kbind normal $MODKEY-C-w,y wmirc
-kbind normal $MODKEY-t 'extern urxvt ''+sb'' -bg ''#000000'' -fg ''#ffffff'' -cr ''#ffffff'' -sl 4000 -fn -artwiz-smoothansi-*-*-*-*-*-*-*-*-*-*-*-*'
-kbind normal $MODKEY-d 'wmir write /wm/ctl detach'
-kbind normal $MODKEY-a 'wmir write /wm/ctl attach'
-kbind normal $MODKEY-S-a 'wmir write /wm/ctl ''detached clients'''
-kbind normal $MODKEY-S-c 'wmir write /wm/sel/layout/sel/geometry 0,0,east,south-20; wmir write /wm/sel/layout/sel/name column'
-kbind normal $MODKEY-S-n 'wmir write /wm/sel/layout/sel/ctl new'
-kbind normal $MODKEY-S-d 'wmir write /wm/sel/layout/sel/ctl destroy'
-kbind normal $MODKEY-S-f 'wmir write /wm/sel/layout/sel/name float'
-kbind normal $MODKEY-Return 'wmir write /wm/sel/ctl ''select zoomed'''
-kbind normal $MODKEY-C-y 'wmir write /wm/ctl new'
-kbind normal $MODKEY-u 'wmir write /wm/sel/layout/sel/frame/sel/locked 0'
-kbind normal $MODKEY-S-u 'wmir write /wm/sel/layout/sel/frame/sel/locked 1'
-kbind normal $MODKEY-$WESTKEY 'wmir write /wm/ctl ''select prev'''
-kbind normal $MODKEY-$EASTKEY 'wmir write /wm/ctl ''select next'''
-kbind normal $MODKEY-Tab 'wmir write /wm/sel/layout/sel/ctl ''select next'''
-kbind normal $MODKEY-$SOUTHKEY 'wmir write /wm/sel/layout/sel/ctl ''select next'''
-kbind normal $MODKEY-$NORTHKEY 'wmir write /wm/sel/layout/sel/ctl ''select prev'''
-kbind normal $MODKEY-S-$WESTKEY 'wmir write /wm/sel/layout/sel/ctl ''select west'''
-kbind normal $MODKEY-S-$EASTKEY 'wmir write /wm/sel/layout/sel/ctl ''select east'''
-kbind normal $MODKEY-S-Tab 'wmir write /wm/sel/layout/sel/frame/sel/ctl ''select next'''
-kbind normal $MODKEY-S-$SOUTHKEY 'wmir write /wm/sel/layout/sel/frame/sel/ctl ''select next'''
-kbind normal $MODKEY-S-$NORTHKEY 'wmir write /wm/sel/layout/sel/frame/sel/ctl ''select prev'''
-kbind normal $MODKEY-space 'wmir write /wm/sel/ctl ''select toggled'''
-kbind normal $MODKEY-S-p 'wmir write /wm/ctl pager'
-for(i in 0 1 2 3 4 5 6 7 8 9) {
- kbind normal $MODKEY-S-$i 'wmir write /wm/ctl ''select '^$i^''''
-}
-
-wmir write /keys/box/font $FONT
-selstyle /keys/box
-kmode normal
-
-# WMIMENU CONFIGURATION
-items actions $WMII_CONFDIR:$HOME/.wmii-3
-wmir create /menu/items/actions/rmpage 'wmir write /wm/ctl destroy'
-items programs $OLD_PATH
-wmir write /menu/font $FONT
-normstyle /menu/nstyle >[2]/dev/null
-selstyle /menu/sstyle >[2]/dev/null
-
-# MISC
-xsetroot -solid black
-status&