commit 3ee60cd19c70e9e05f9ab7a7df5072916d513edb
parent 967912b82bf32710b07b1f49937075c73306e95a
Author: Kris Maglione <jg@suckless.org>
Date: Sat, 19 Jan 2008 22:30:37 -0500
Merge
Diffstat:
32 files changed, 1125 insertions(+), 826 deletions(-)
diff --git a/cmd/util.c b/cmd/util.c
@@ -46,6 +46,30 @@ fatal(const char *fmt, ...) {
exit(1);
}
+char*
+vsxprint(const char *fmt, va_list ap) {
+ static char* bufs[16];
+ static long nbuf;
+ int id;
+
+ id = nbuf++ % nelem(bufs);
+ if(bufs[id])
+ free(bufs[id]);
+ bufs[id] = vsmprint(fmt, ap);
+ return bufs[id];
+}
+
+char*
+sxprint(const char *fmt, ...) {
+ va_list ap;
+ char *ret;
+
+ va_start(ap, fmt);
+ ret = vsxprint(fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
void
_die(char *file, int line, char *msg) {
fprint(2, "%s: dieing at %s:%d: %s\n",
@@ -150,13 +174,6 @@ min(int a, int b) {
return b;
}
-char *
-str_nil(char *s) {
- if(s)
- return s;
- return "<nil>";
-}
-
int
utflcpy(char *to, const char *from, int l) {
char *p;
diff --git a/cmd/wihack.sh b/cmd/wihack.sh
@@ -7,6 +7,7 @@ usage() {
}
checkarg='[ ${#@} -gt 0 ] || usage'
+export WMII_HACK_TIME=$(date +%s)
while [ ${#@} -gt 0 ]
do
diff --git a/cmd/wmii/Makefile b/cmd/wmii/Makefile
@@ -8,15 +8,17 @@ TARG = wmii
HFILES= dat.h fns.h
LIB = ${LIBIXP}
-LDFLAGS += -lm ${LIBX11} -lXext ${LIBICONV} -lregexp9 -lbio -lfmt -lutf
+LDFLAGS += -lm ${LIBX11} -lXext -lXrandr ${LIBICONV} -lregexp9 -lbio -lfmt -lutf
CFLAGS += ${INCX11} ${INCICONV} -DVERSION=\"${VERSION}\" \
-DIXP_NEEDAPI=86
OBJ = area \
bar \
client \
column \
+ div \
event \
ewmh \
+ float \
frame \
fs \
geom \
@@ -30,6 +32,7 @@ OBJ = area \
utf \
view \
x11 \
+ xext \
../util
include ${ROOT}/mk/one.mk
diff --git a/cmd/wmii/area.c b/cmd/wmii/area.c
@@ -30,12 +30,12 @@ area_idx(Area *a) {
char*
area_name(Area *a) {
- static char buf[16];
-
+
+ if(a == nil)
+ return "<nil>";
if(a->floating)
return "~";
- snprint(buf, sizeof(buf), "%d", area_idx(a));
- return buf;
+ return sxprint("%d", area_idx(a));
}
Area*
@@ -46,13 +46,13 @@ area_create(View *v, Area *pos, uint w) {
int colnum;
Area *a;
- minwidth = Dx(screen->r)/NCOL;
+ minwidth = Dx(v->r)/NCOL;
i = 0;
- for(a = v->area; a != pos; a = a->next)
- i++;
+ if(pos)
+ i = area_idx(pos);
areanum = 0;
- for(a = v->area; a; a = a->next)
+ for(a=v->area; a; a=a->next)
areanum++;
colnum = areanum - 1;
@@ -60,19 +60,19 @@ area_create(View *v, Area *pos, uint w) {
if(colnum >= 0) {
w = view_newcolw(v, i);
if (w == 0)
- w = Dx(screen->r) / (colnum + 1);
+ w = Dx(v->r) / (colnum + 1);
}
else
- w = Dx(screen->r);
+ w = Dx(v->r);
}
if(w < minwidth)
w = minwidth;
- if(colnum && (colnum * minwidth + w) > Dx(screen->r))
+ if(colnum && (colnum * minwidth + w) > Dx(v->r))
return nil;
if(pos)
- view_scale(v, Dx(screen->r) - w);
+ view_scale(v, Dx(v->r) - w);
a = emallocz(sizeof *a);
a->view = v;
@@ -81,10 +81,9 @@ area_create(View *v, Area *pos, uint w) {
a->frame = nil;
a->sel = nil;
- a->r = screen->r;
+ a->r = v->r;
a->r.min.x = 0;
a->r.max.x = w;
- a->r.max.y = screen->brect.min.y;
if(pos) {
a->next = pos->next;
@@ -111,7 +110,6 @@ area_create(View *v, Area *pos, uint w) {
void
area_destroy(Area *a) {
- Client *c;
Area *ta;
View *v;
int idx;
@@ -124,10 +122,6 @@ area_destroy(Area *a) {
if(v->revert == a)
v->revert = nil;
- for(c=client; c; c=c->next)
- if(c->revert == a)
- c->revert = nil;
-
idx = area_idx(a);
if(a->prev && !a->prev->floating)
@@ -135,9 +129,6 @@ area_destroy(Area *a) {
else
ta = a->next;
- if(a == v->colsel)
- v->colsel = ta;
-
/* Can only destroy the floating area when destroying a
* view---after destroying all columns.
*/
@@ -147,9 +138,9 @@ area_destroy(Area *a) {
if(a->next)
a->next->prev = a->prev;
- if(ta && v->sel == a) {
+ if(ta && v->sel == a)
area_focus(ta);
- }
+ view_arrange(v);
event("DestroyArea %d\n", idx);
/* Deprecated */
event("DestroyColumn %d\n", idx);
@@ -159,6 +150,7 @@ area_destroy(Area *a) {
void
area_moveto(Area *to, Frame *f) {
+ Rectangle tr;
Area *from;
assert(to->view == f->view);
@@ -166,16 +158,18 @@ area_moveto(Area *to, Frame *f) {
from = f->area;
if(to->floating != from->floating) {
- Rectangle tr;
-
+ /* XXX: This must be changed. */
tr = f->revert;
f->revert = f->r;
- f->r = temp;
+ f->r = tr;
}
- f->client->revert = from;
area_detach(f);
area_attach(to, f);
+
+ /* Temporary kludge. */
+ if(!to->floating && to->floating != from->floating)
+ column_resizeframe(f, &tr);
}
void
@@ -191,220 +185,29 @@ area_setsel(Area *a, Frame *f) {
void
area_attach(Area *a, Frame *f) {
- uint nframe;
- Frame *ft;
- Client *c;
-
- c = f->client;
f->area = a;
+ if(a->floating)
+ float_attach(a, f);
+ else
+ column_attach(a, f);
- nframe = 0;
- for(ft=a->frame; ft; ft=ft->anext)
- nframe++;
- nframe = max(nframe, 1);
-
- c->floating = a->floating;
- if(!a->floating) {
- f->r = a->r;
- f->r.max.y = Dy(a->r) / n_frame;
- }
-
- frame_insert(a->sel, f);
-
- if(a->floating) {
- place_frame(f);
- client_resize(f->client, f->r);
- }
-
- if(!a->sel)
- area_setsel(a, f);
view_restack(a->view);
- if(!a->floating)
- column_arrange(a, False);
-
if(a->frame)
assert(a->sel);
}
void
area_detach(Frame *f) {
- Frame *pr;
- Client *c;
Area *a;
- View *v;
a = f->area;
- v = a->view;
- c = f->client;
-
- pr = f->aprev;
- frame_remove(f);
-
- if(!a->floating) {
- if(a->frame)
- column_arrange(a, False);
- else {
- if(v->area->next->next)
- area_destroy(a);
- else if((a->frame == nil) && (v->area->frame))
- area_focus(v->area);
- view_arrange(v);
- }
- }else if(v->oldsel)
- area_focus(v->oldsel);
- else if(!a->frame) {
- if(v->colsel->frame)
- area_focus(v->colsel);
- }else
- assert(a->sel);
-
- if(a->sel == f) {
- if(!pr)
- pr = a->frame;
- area_setsel(a, pr);
- }
-}
-static void
-bit_set(uint *field, uint width, uint x, uint y, int set) {
- enum { divisor = sizeof(uint) * 8 };
- uint bx, mask;
- div_t d;
-
- d = div(x, divisor);
- bx = d.quot;
- mask = 1 << d.rem;
- if(set)
- field[y*width + bx] |= mask;
+ if(a->floating)
+ float_detach(f);
else
- field[y*width + bx] &= ~mask;
-}
-
-static Bool
-bit_get(uint *field, uint width, uint x, uint y) {
- enum { divisor = sizeof(uint) * 8 };
- uint bx, mask;
- div_t d;
-
- d = div(x, divisor);
- bx = d.quot;
- mask = 1 << d.rem;
-
- return (field[y*width + bx] & mask) != 0;
-}
-
-static void
-place_frame(Frame *f) {
- enum { divisor = sizeof(uint) * 8 };
- enum { dx = 8, dy = 8 };
-
- static uint mwidth, mx, my;
- static uint *field = nil;
- Align align;
- Point p1 = ZP;
- Point p2 = ZP;
- Rectangle *rects;
- Frame *fr;
- Client *c;
- Area *a;
- bool fit;
- uint i, j, x, y, cx, cy, maxx, maxy, diff, num;
- int snap;
-
- snap = Dy(screen->r) / 66;
- num = 0;
- fit = False;
- align = CENTER;
-
- a = f->area;
- c = f->client;
-
- if(c->trans)
- return;
- if(c->fullscreen || c->w.hints->position || starting) {
- f->r = gravclient(c, c->r);
- return;
- }
- if(!field) {
- mx = Dx(screen->r) / dx;
- my = Dy(screen->r) / dy;
- mwidth = ceil((float)mx / divisor);
- field = emallocz(sizeof(uint) * mwidth * my);
- }
-
- SET(cx);
- SET(cy);
- memset(field, ~0, (sizeof(uint) * mwidth * my));
- for(fr=a->frame; fr; fr=fr->anext) {
- if(fr == f) {
- cx = Dx(f->r) / dx;
- cy = Dx(f->r) / dy;
- continue;
- }
-
- if(fr->r.min.x < 0)
- x = 0;
- else
- x = fr->r.min.x / dx;
-
- if(fr->r.min.y < 0)
- y = 0;
- else
- y = fr->r.min.y / dy;
-
- maxx = fr->r.max.x / dx;
- maxy = fr->r.max.y / dy;
- for(j = y; j < my && j < maxy; j++)
- for(i = x; i < mx && i < maxx; i++)
- bit_set(field, mwidth, i, j, False);
- }
-
- for(y = 0; y < my; y++)
- for(x = 0; x < mx; x++) {
- if(bit_get(field, mwidth, x, y)) {
- for(i = x; i < mx; i++)
- if(bit_get(field, mwidth, i, y) == 0)
- break;
- for(j = y; j < my; j++)
- if(bit_get(field, mwidth, x, j) == 0)
- break;
-
- if(((i - x) * (j - y) > (p2.x - p1.x) * (p2.y - p1.y))
- && (i - x > cx) && (j - y > cy))
- {
- fit = True;
- p1.x = x;
- p1.y = y;
- p2.x = i;
- p2.y = j;
- }
- }
- }
-
- if(fit) {
- p1.x *= dx;
- p1.y *= dy;
- }
-
- if(!fit || (p1.x + Dx(f->r) > a->r.max.x)) {
- diff = Dx(a->r) - Dx(f->r);
- p1.x = a->r.min.x + (random() % max(diff, 1));
- }
-
- if(!fit && (p1.y + Dy(f->r) > a->r.max.y)) {
- diff = Dy(a->r) - Dy(f->r);
- p1.y = a->r.min.y + (random() % max(diff, 1));
- }
-
- p1 = subpt(p1, f->r.min);
- f->r = rectaddpt(f->r, p1);
-
- rects = rects_of_view(a->view, &num, nil);
- snap_rect(rects, num, &f->r, &align, snap);
- if(rects)
- free(rects);
+ column_detach(f);
}
void
@@ -417,7 +220,12 @@ area_focus(Area *a) {
f = a->sel;
old_a = v->sel;
+ if(view_fullscreen_p(v) && !a->floating)
+ return;
+
v->sel = a;
+ if(!a->floating)
+ v->selcol = area_idx(a);
if((old_a) && (a->floating != old_a->floating))
v->revert = old_a;
diff --git a/cmd/wmii/bar.c b/cmd/wmii/bar.c
@@ -149,9 +149,9 @@ bar_draw(WMScreen *s) {
fill(screen->ibuf, r, def.normcolor.bg);
for(nb = 0; nb < nelem(s->bar); nb++)
for(b = s->bar[nb]; b; b=b->next) {
- align = CENTER;
+ align = Center;
if(b == s->bar[BarRight])
- align = EAST;
+ align = East;
fill(screen->ibuf, b->r, b->col.bg);
drawstring(screen->ibuf, def.font, b->r, align, b->text, b->col.fg);
border(screen->ibuf, b->r, 1, b->col.border);
diff --git a/cmd/wmii/client.c b/cmd/wmii/client.c
@@ -3,9 +3,8 @@
* See LICENSE file for license details.
*/
#include "dat.h"
+#include <assert.h>
#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
#include <X11/Xatom.h>
#include "fns.h"
@@ -33,10 +32,14 @@ group_init(Client *c) {
XWindow w;
long n;
- n = getprop_long(&c->w, "WM_CLIENT_LEADER", "WINDOW", 0L, &ret, 1L);
- if(n == 0)
- return;
- w = *ret;
+ w = c->w.hints->group;
+ if(w == 0) {
+ /* Not quite ICCCM compliant, but it seems to work. */
+ n = getprop_long(&c->w, "WM_CLIENT_LEADER", "WINDOW", 0L, &ret, 1L);
+ if(n == 0)
+ return;
+ w = *ret;
+ }
for(g=group; g; g=g->next)
if(g->leader == w)
@@ -91,6 +94,7 @@ Client*
client_create(XWindow w, XWindowAttributes *wa) {
Client **t, *c;
WinAttr fwa;
+ Point p;
c = emallocz(sizeof(Client));
c->border = wa->border_width;
@@ -160,6 +164,10 @@ client_manage(Client *c) {
Frame *f;
char *tags;
+ if(Dx(c->r) == Dx(screen->r))
+ if(Dy(c->r) == Dy(screen->r))
+ fullscreen(c, true);
+
tags = getprop_string(&c->w, "_WMII_TAGS");
trans = win2client(c->trans);
@@ -167,15 +175,15 @@ client_manage(Client *c) {
trans = group_leader(c->group);
if(tags)
- utflcpy(c->tags, tags, sizeof(c->tags));
+ utflcpy(c->tags, tags, sizeof c->tags);
else if(trans)
- utflcpy(c->tags, trans->tags, sizeof(c->tags));
+ utflcpy(c->tags, trans->tags, sizeof c->tags);
free(tags);
- if(c->tags[0])
- apply_tags(c, c->tags);
- else
+ /* Maybe not the best idea... */
+ if(!trans || !c->tags[0])
apply_rules(c);
+ apply_tags(c, c->tags);
if(!starting)
view_update_all();
@@ -185,9 +193,9 @@ client_manage(Client *c) {
|| selclient() && (selclient()->group == c->group);
f = c->sel;
- if((f->view == screen->sel)
- && (!(c->w.ewmh.type & TypeSplash))
- && newgroup) {
+ if(f->view == screen->sel)
+ if(!(c->w.ewmh.type & TypeSplash))
+ if(newgroup) {
if(f->area != f->view->sel)
f->view->oldsel = f->view->sel;
focus(c, false);
@@ -210,7 +218,7 @@ void
client_destroy(Client *c) {
int (*handler)(Display*, XErrorEvent*);
Rectangle r;
- char *dummy;
+ char *none;
Client **tc;
bool hide;
@@ -233,9 +241,8 @@ client_destroy(Client *c) {
/* In case the client is already unmapped */
handler = XSetErrorHandler(ignoreerrors);
- dummy = nil;
- client_setviews(c, &dummy);
- client_unmap(c, IconicState);
+ none = nil;
+ client_setviews(c, &none);
sethandler(&c->w, nil);
if(hide)
@@ -330,6 +337,24 @@ client_grav(Client *c, Rectangle rd) {
}
}
+bool
+client_floats_p(Client *c) {
+ return c->trans
+ || c->floating
+ || c->fixedsize
+ || c->titleless
+ || c->borderless
+ || c->fullscreen
+ || (c->w.ewmh.type & (TypeDialog|TypeSplash|TypeDock));
+}
+
+Frame*
+client_groupframe(Client *c, View *v) {
+ if(c->group && c->group->client)
+ return client_viewframe(c->group->client, v);
+ return nil;
+}
+
Rectangle
frame_hints(Frame *f, Rectangle r, Align sticky) {
Rectangle or;
@@ -354,16 +379,16 @@ frame_hints(Frame *f, Rectangle r, Align sticky) {
}
p = ZP;
- if((sticky&(EAST|WEST)) == EAST)
+ if((sticky&(East|West)) == East)
p.x = Dx(or) - Dx(r);
- if((sticky&(NORTH|SOUTH)) == SOUTH)
+ if((sticky&(North|South)) == South)
p.y = Dy(or) - Dy(r);
return rectaddpt(r, p);
}
static void
-client_setstate(Client *c, int state) {
+client_setstate(Client * c, int state) {
long data[] = { state, None };
changeprop_long(&c->w, "WM_STATE", "WM_STATE", data, nelem(data));
@@ -403,8 +428,10 @@ focus(Client *c, bool user) {
f = c->sel;
if(!f)
return;
+ /*
if(!user && c->noinput)
return;
+ */
v = f->view;
if(v != screen->sel)
@@ -433,9 +460,7 @@ client_focus(Client *c) {
setfocus(screen->barwin, RevertToParent);
event("ClientFocus %C\n", c);
- write_event("ClientFocus %C\n", c);
-
- XSync(display, False);
+ sync();
flushevents(FocusChangeMask, True);
}
}
@@ -507,24 +532,10 @@ client_configure(Client *c) {
sendevent(&c->w, false, StructureNotifyMask, (XEvent*)&e);
}
-static void
-client_sendmessage(Client *c, char *name, char *value) {
- XClientMessageEvent e;
-
- e.type = ClientMessage;
- e.window = c->w.w;
- e.message_type = xatom(name);
- e.format = 32;
- e.data.l[0] = xatom(value);
- e.data.l[1] = xtime;
- sendevent(&c->w, false, NoEventMask, (XEvent*)&e);
- sync();
-}
-
void
client_kill(Client *c, bool nice) {
if(nice && (c->proto & ProtoDelete)) {
- client_sendmessage(c, "WM_PROTOCOLS", "WM_DELETE_WINDOW");
+ sendmessage(&c->w, "WM_PROTOCOLS", "WM_DELETE_WINDOW", 0, 0, 0);
ewmh_pingclient(c);
}
else
@@ -534,6 +545,7 @@ client_kill(Client *c, bool nice) {
void
fullscreen(Client *c, int fullscreen) {
Frame *f;
+ bool wassel;
if(fullscreen == Toggle)
fullscreen = c->fullscreen ^ On;
@@ -544,37 +556,42 @@ fullscreen(Client *c, int fullscreen) {
c->fullscreen = fullscreen;
ewmh_updatestate(c);
- if((f = c->sel)) {
- if(fullscreen) {
- if(f->area->floating)
- f->revert = f->r;
- else {
- f->r = f->revert;
- area_moveto(f->view->area, f);
+ if(!fullscreen)
+ for(f=c->frame; f; f=f->cnext) {
+ if(f->oldarea == 0)
+ frame_resize(f, f->oldr); /* XXX: oldr Replace with floatr */
+ else if(f->oldarea > 0) {
+ wassel = (f == f->area->sel);
+ area_moveto(view_findarea(f->view, f->oldarea, true), f);
+ f->revert = f->oldr; /* XXX: oldr */
+ if(wassel)
+ frame_focus(f);
}
- focus(c, true);
- }else
- frame_resize(f, f->revert);
- if(f->view == screen->sel)
- view_focus(screen, f->view);
+ }
+ else {
+ for(f=c->frame; f; f=f->cnext)
+ f->oldarea = -1;
+ if((f = c->sel))
+ if(f->view == screen->sel)
+ view_focus(screen, f->view);
}
}
void
-client_seturgent(Client *c, int urgent, bool write) {
+client_seturgent(Client *c, bool urgent, int from) {
XWMHints *wmh;
- char *cwrite, *cnot;
+ char *cfrom, *cnot;
Frame *f, *ff;
Area *a;
if(urgent == Toggle)
urgent = c->urgent ^ On;
- cwrite = (write ? "Manager" : "Client");
+ cfrom = (from == UrgManager ? "Manager" : "Client");
cnot = (urgent ? "" : "Not");
if(urgent != c->urgent) {
- event("%sUrgent %C %s\n", cnot, c, cwrite);
+ event("%sUrgent %C %s\n", cnot, c, cfrom);
c->urgent = urgent;
ewmh_updatestate(c);
if(c->sel) {
@@ -587,12 +604,12 @@ client_seturgent(Client *c, int urgent, bool write) {
for(ff=a->frame; ff; ff=ff->anext)
if(ff->client->urgent) break;
if(urgent || ff == nil)
- event("%sUrgentTag %s %s\n", cnot, cwrite, f->view->name);
+ event("%sUrgentTag %s %s\n", cnot, cfrom, f->view->name);
}
}
}
- if(write) {
+ if(from == UrgManager) {
wmh = XGetWMHints(display, c->w.w);
if(wmh == nil)
wmh = emallocz(sizeof *wmh);
@@ -681,16 +698,16 @@ client_prop(Client *c, Atom a) {
char **class;
int n;
- if(a == xatom("WM_PROTOCOLS")) {
+ if(a == xatom("WM_PROTOCOLS"))
c->proto = winprotocols(&c->w);
- }
- else if(a == xatom("_NET_WM_NAME")) {
+ else
+ if(a == xatom("_NET_WM_NAME"))
goto wmname;
- }
- else if(a == xatom("_MOTIF_WM_HINTS")) {
+ else
+ if(a == xatom("_MOTIF_WM_HINTS"))
updatemwm(c);
- }
- else switch (a) {
+ else
+ switch (a) {
default:
ewmh_prop(c, a);
break;
@@ -706,7 +723,7 @@ client_prop(Client *c, Atom a) {
wmh = XGetWMHints(display, c->w.w);
if(wmh) {
c->noinput = !((wmh->flags&InputFocus) && wmh->input);
- client_seturgent(c, (wmh->flags & XUrgencyHint) != 0, False);
+ client_seturgent(c, (wmh->flags & XUrgencyHint) != 0, UrgClient);
XFree(wmh);
}
break;
@@ -752,9 +769,6 @@ configreq_event(Window *w, XConfigureRequestEvent *e) {
cr = r;
r = client_grav(c, r);
- if((Dx(cr) == Dx(screen->r)) && (Dy(cr) == Dy(screen->r)))
- fullscreen(c, True);
-
if(c->sel->area->floating) {
client_resize(c, r);
sync();
@@ -956,7 +970,9 @@ apply_tags(Client *c, const char *tags) {
j = 0;
while(buf[n] && n < sizeof(buf) && j < 32) {
for(i = n; i < sizeof(buf) - 1; i++)
- if(buf[i] == '+' || buf[i] == '-' || buf[i] == '\0')
+ if(buf[i] == '+'
+ || buf[i] == '-'
+ || buf[i] == '\0')
break;
last = buf[i];
buf[i] = '\0';
@@ -964,7 +980,8 @@ apply_tags(Client *c, const char *tags) {
cur = nil;
if(!strcmp(buf+n, "~"))
c->floating = add;
- else if(!strcmp(buf+n, "!") || !strcmp(buf+n, "sel"))
+ else
+ if(!strcmp(buf+n, "!") || !strcmp(buf+n, "sel"))
cur = screen->sel->name;
else if(!Mbsearch(buf+n, badtags, bsstrcmp))
cur = buf+n;
@@ -981,30 +998,25 @@ apply_tags(Client *c, const char *tags) {
}
}
- switch(last) {
- case '+':
+ if(last == '+')
add = True;
- break;
- case '-':
+ if(last == '-')
add = False;
- break;
- case '\0':
+ if(last == '\0')
buf[n] = '\0';
- break;
- }
}
if(!j)
return;
- qsort(toks, j, sizeof(char *), strpcmp);
+ qsort(toks, j, sizeof *toks, strpcmp);
c->tags[0] = '\0';
for(i=0, n=0; i < j; i++)
if(n == 0 || strcmp(toks[i], toks[n-1])) {
if(i > 0)
- strlcat(c->tags, "+", sizeof(c->tags));
- strlcat(c->tags, toks[i], sizeof(c->tags));
+ strlcat(c->tags, "+", sizeof c->tags);
+ strlcat(c->tags, toks[i], sizeof c->tags);
toks[n++] = toks[i];
}
toks[n] = nil;
@@ -1018,17 +1030,13 @@ void
apply_rules(Client *c) {
Rule *r;
- if(strlen(c->tags))
- return;
-
if(def.tagrules.string)
for(r=def.tagrules.rule; r; r=r->next)
if(regexec(r->regex, c->props, nil, 0)) {
apply_tags(c, r->value);
- if(c->tags[0] && strcmp(c->tags, "nil"))
- break;
+ break;
}
if(c->tags[0] == '\0')
- apply_tags(c, "nil");
+ apply_tags(c, "sel");
}
diff --git a/cmd/wmii/column.c b/cmd/wmii/column.c
@@ -1,18 +1,13 @@
/* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
- * Copyright ©2006-2007 Kris Maglione <fbsdaemon@gmail.com>
+ * Copyright ©2006-2008 Kris Maglione <fbsdaemon@gmail.com>
* See LICENSE file for license details.
*/
#include "dat.h"
#include <assert.h>
#include <math.h>
-#include <string.h>
#include <strings.h>
#include "fns.h"
-static Image *divimg, *divmask;
-static CTuple divc;
-static Handlers divhandler;
-
char *modes[] = {
[Coldefault] = "default",
[Colstack] = "stack",
@@ -30,158 +25,87 @@ str2colmode(const char *str) {
}
char*
-colmode2str(int i) {
+colmode2str(uint i) {
if(i < nelem(modes))
return modes[i];
return nil;
}
-static Divide*
-getdiv(Divide **dp) {
- WinAttr wa;
- Divide *d;
-
- if(*dp)
- return *dp;
-
- d = emallocz(sizeof *d);
-
- wa.override_redirect = True;
- wa.cursor = cursor[CurDHArrow];
- wa.event_mask =
- ExposureMask
- | EnterWindowMask
- | ButtonPressMask
- | ButtonReleaseMask;
- d->w = createwindow(&scr.root, Rect(0, 0, 1, 1), scr.depth, InputOutput, &wa,
- CWOverrideRedirect
- | CWEventMask
- | CWCursor);
- d->w->aux = d;
- sethandler(d->w, &divhandler);
-
- *dp = d;
- return d;
-}
+Area*
+column_new(View *v, Area *pos, uint w) {
+ Area *a;
-static void
-mapdiv(Divide *d) {
- mapwin(d->w);
-}
+ a = area_create(v, pos, w);
+ if(!a)
+ return nil;
-static void
-unmapdiv(Divide *d) {
- unmapwin(d->w);
+ view_arrange(v);
+ if(v == screen->sel)
+ view_focus(screen, v);
+ return a;
}
void
-div_set(Divide *d, int x) {
- Rectangle r;
-
- d->x = x;
- r = rectaddpt(divimg->r, Pt(x - Dx(divimg->r)/2, 0));
- r.max.y = screen->brect.min.y;
-
- reshapewin(d->w, r);
- mapdiv(d);
-}
-
-static void
-drawimg(Image *img, ulong cbg, ulong cborder) {
- Point pt[6];
+column_insert(Area *a, Frame *f, Frame *pos) {
- pt[0] = Pt(0, 0);
- pt[1] = Pt(Dx(img->r)/2 - 1, Dx(img->r)/2 - 1);
-
- pt[2] = Pt(pt[1].x, Dy(img->r));
- pt[3] = Pt(Dx(img->r)/2, pt[2].y);
-
- pt[4] = Pt(pt[3].x, Dx(img->r)/2 - 1);
- pt[5] = Pt(Dx(img->r) - 1, 0);
-
- fillpoly(img, pt, nelem(pt), cbg);
- drawpoly(img, pt, nelem(pt), CapNotLast, 1, cborder);
-}
-
-static void
-drawdiv(Divide *d) {
- copyimage(d->w, divimg->r, divimg, ZP);
- setshapemask(d->w, divmask, ZP);
+ f->area = a;
+ f->client->floating = false;
+ f->column = area_idx(a);
+ frame_insert(f, pos);
}
-static void
-update_imgs(void) {
- Divide *d;
- int w, h;
-
- w = 2 * (labelh(def.font) / 3);
- w = max(w, 10);
- h = Dy(screen->r);
-
- if(divimg) {
- if(w == Dx(divimg->r) && h == Dy(divimg->r)
- && !memcmp(&divc, &def.normcolor, sizeof(divc)))
- return;
- freeimage(divimg);
- freeimage(divmask);
- }
-
- divimg = allocimage(w, h, scr.depth);
- divmask = allocimage(w, h, 1);
- divc = def.normcolor;
-
- fill(divmask, divmask->r, 0);
- drawimg(divmask, 1, 1);
- drawimg(divimg, divc.bg, divc.border);
-
- for(d = divs; d && d->w->mapped; d = d->next)
- drawdiv(d);
+void
+column_attach(Area *a, Frame *f) {
+ uint nframe;
+ Frame *ft;
+
+ nframe = 0;
+ for(ft=a->frame; ft; ft=ft->anext)
+ nframe++;
+ nframe = max(nframe, 1);
+
+ f->r = a->r;
+ f->r.max.y = Dy(a->r) / nframe;
+
+ column_insert(a, f, a->sel);
+ if(a->sel == nil)
+ area_setsel(a, f);
+ column_arrange(a, false);
}
void
-div_update_all(void) {
- Divide **dp, *d;
+column_remove(Frame *f, bool arrange) {
+ Client *c;
+ Frame *pr;
Area *a;
View *v;
- update_imgs();
-
- v = screen->sel;
- dp = &divs;
- for(a = v->area->next; a; a = a->next) {
- d = getdiv(dp);
- dp = &d->next;
- div_set(d, a->r.min.x);
+ a = f->area;
+ v = a->view;
+ c = f->client;
- if(!a->next) {
- d = getdiv(dp);
- dp = &d->next;
- div_set(d, a->r.max.x);
- }
- }
- for(d = *dp; d; d = d->next)
- unmapdiv(d);
-}
+ pr = f->aprev;
-/* Div Handlers */
-static void
-bdown_event(Window *w, XButtonEvent *e) {
- Divide *d;
+ frame_remove(f);
- USED(e);
-
- d = w->aux;
- mouse_resizecol(d);
-}
+ f->area = nil;
+ if(a->sel == f) {
+ if(!pr)
+ pr = a->frame;
+ a->sel = nil;
+ area_setsel(a, pr);
+ }
-static void
-expose_event(Window *w, XExposeEvent *e) {
- Divide *d;
-
- USED(e);
-
- d = w->aux;
- drawdiv(d);
+ if(a->frame) {
+ if(arrange)
+ column_arrange(a, False);
+ }
+ else {
+ if(v->area->next->next)
+ area_destroy(a);
+ else if(v->area->frame)
+ area_focus(v->area);
+ }
}
static Handlers divhandler = {
@@ -197,14 +121,11 @@ column_new(View *v, Area *pos, uint w) {
if(!a)
return nil;
- view_arrange(v);
- if(v == screen->sel)
- view_focus(screen, v);
- return a;
+ column_remove(f, true);
}
static void
-scale_column(Area *a) {
+column_scale(Area *a) {
Frame *f, **fp;
uint minh, yoff, dy;
uint ncol, nuncol;
@@ -354,7 +275,7 @@ column_arrange(Area *a, bool dirty) {
die("can't get here");
break;
}
- scale_column(a);
+ column_scale(a);
resize:
if(a->view == screen->sel) {
view_restack(a->view);
@@ -386,7 +307,7 @@ column_resize(Area *a, int w) {
}
static void
-resize_colframeh(Frame *f, Rectangle *r) {
+column_resizeframe_h(Frame *f, Rectangle *r) {
Area *a;
Frame *fn, *fp;
uint minh;
@@ -430,7 +351,7 @@ column_resizeframe(Frame *f, Rectangle *r) {
v = a->view;
maxx = r->max.x;
- minw = Dx(screen->r) / NCOL;
+ minw = Dx(v->r) / NCOL;
al = a->prev;
ar = a->next;
@@ -443,7 +364,7 @@ column_resizeframe(Frame *f, Rectangle *r) {
if(ar)
maxx = min(maxx, a->r.max.x - minw);
else
- maxx = min(maxx, screen->r.max.x);
+ maxx = min(maxx, v->r.max.x);
dx = a->r.min.x - r->min.x;
dw = maxx - a->r.max.x;
@@ -456,7 +377,7 @@ column_resizeframe(Frame *f, Rectangle *r) {
column_arrange(ar, False);
}
- resize_colframeh(f, r);
+ column_resizeframe_h(f, r);
a->r.max.x = maxx;
view_arrange(a->view);
diff --git a/cmd/wmii/dat.h b/cmd/wmii/dat.h
@@ -1,4 +1,4 @@
-/* © 2004-2006 Anselm R. Garbe <garbeam at gmail dot com>
+/* Copyright ©2007-2008 Kris Maglione <jg@suckless.org>
* See LICENSE file for license details.
*/
@@ -6,12 +6,15 @@
#define IXP_P9_STRUCTS
#define IXP_NO_P9_
#include <regexp9.h>
+#include <stdbool.h>
#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
#include <ixp.h>
#include <util.h>
#include <utf.h>
#include <fmt.h>
-#include "x11.h"
+#include <x11.h>
#define FONT "-*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*"
#define FOCUSCOLORS "#ffffff #335577 #447799"
@@ -21,6 +24,11 @@ enum {
PingTime = 10000,
};
+enum {
+ UrgManager,
+ UrgClient,
+};
+
enum EWMHType {
TypeDesktop = 1<<0,
TypeDock = 1<<1,
@@ -114,7 +122,6 @@ struct Bar {
struct Client {
Client* next;
- Area* revert;
Frame* frame;
Frame* sel;
Window w;
@@ -152,13 +159,16 @@ struct Frame {
Frame* aprev;
Frame* snext;
Frame* sprev;
+ Client* client;
View* view;
Area* area;
- Client* client;
+ int oldarea;
+ int column;
ushort id;
bool collapsed;
float ratio;
Rectangle r;
+ Rectangle oldr;
Rectangle crect;
Rectangle revert;
Rectangle grabbox;
@@ -219,9 +229,10 @@ struct View {
ushort id;
Area* area;
Area* sel;
- Area* colsel;
Area* oldsel;
Area* revert;
+ int selcol;
+ Rectangle r;
};
#ifndef EXTERN
@@ -296,4 +307,12 @@ typedef void (*XHandler)(XEvent*);
EXTERN XHandler handler[LASTEvent];
/* Misc */
+EXTERN bool starting;
+EXTERN char* user;
+EXTERN char* execstr;
+EXTERN int debug;
+EXTERN long xtime;
+
+#define Debug(x) if(debug&(x))
+#define Dprint(x, ...) BLOCK( Debug(x) fprint(2, __VA_ARGS__) )
diff --git a/cmd/wmii/div.c b/cmd/wmii/div.c
@@ -0,0 +1,163 @@
+/* Copyright ©2006-2008 Kris Maglione <fbsdaemon@gmail.com>
+ * See LICENSE file for license details.
+ */
+#include "dat.h"
+#include "fns.h"
+
+static Image *divimg, *divmask;
+static CTuple divc;
+static Handlers handlers;
+
+static Divide*
+getdiv(Divide **dp) {
+ WinAttr wa;
+ Divide *d;
+
+ if(*dp)
+ return *dp;
+
+ d = emallocz(sizeof *d);
+
+ wa.override_redirect = True;
+ wa.cursor = cursor[CurDHArrow];
+ wa.event_mask =
+ ExposureMask
+ | EnterWindowMask
+ | ButtonPressMask
+ | ButtonReleaseMask;
+ d->w = createwindow(&scr.root, Rect(0, 0, 1, 1), scr.depth, InputOutput, &wa,
+ CWOverrideRedirect
+ | CWEventMask
+ | CWCursor);
+ d->w->aux = d;
+ sethandler(d->w, &handlers);
+
+ *dp = d;
+ return d;
+}
+
+static void
+mapdiv(Divide *d) {
+ mapwin(d->w);
+}
+
+static void
+unmapdiv(Divide *d) {
+ unmapwin(d->w);
+}
+
+void
+div_set(Divide *d, int x) {
+ Rectangle r;
+
+ d->x = x;
+ r = rectaddpt(divimg->r, Pt(x - Dx(divimg->r)/2, 0));
+ r.max.y = screen->brect.min.y;
+
+ reshapewin(d->w, r);
+ mapdiv(d);
+}
+
+static void
+drawimg(Image *img, ulong cbg, ulong cborder) {
+ Point pt[6];
+
+ pt[0] = Pt(0, 0);
+ pt[1] = Pt(Dx(img->r)/2 - 1, Dx(img->r)/2 - 1);
+
+ pt[2] = Pt(pt[1].x, Dy(img->r));
+ pt[3] = Pt(Dx(img->r)/2, pt[2].y);
+
+ pt[4] = Pt(pt[3].x, Dx(img->r)/2 - 1);
+ pt[5] = Pt(Dx(img->r) - 1, 0);
+
+ fillpoly(img, pt, nelem(pt), cbg);
+ drawpoly(img, pt, nelem(pt), CapNotLast, 1, cborder);
+}
+
+static void
+drawdiv(Divide *d) {
+ copyimage(d->w, divimg->r, divimg, ZP);
+ setshapemask(d->w, divmask, ZP);
+}
+
+static void
+update_imgs(void) {
+ Divide *d;
+ int w, h;
+
+ w = 2 * (labelh(def.font) / 3);
+ w = max(w, 10);
+ h = Dy(screen->sel->r);
+
+ if(divimg) {
+ if(w == Dx(divimg->r) && h == Dy(divimg->r)
+ && !memcmp(&divc, &def.normcolor, sizeof(divc)))
+ return;
+ freeimage(divimg);
+ freeimage(divmask);
+ }
+
+ divimg = allocimage(w, h, scr.depth);
+ divmask = allocimage(w, h, 1);
+ divc = def.normcolor;
+
+ fill(divmask, divmask->r, 0);
+ drawimg(divmask, 1, 1);
+ drawimg(divimg, divc.bg, divc.border);
+
+ for(d = divs; d && d->w->mapped; d = d->next)
+ drawdiv(d);
+}
+
+void
+div_update_all(void) {
+ Divide **dp, *d;
+ Area *a;
+ View *v;
+
+ update_imgs();
+
+ v = screen->sel;
+ dp = &divs;
+ for(a = v->area->next; a; a = a->next) {
+ d = getdiv(dp);
+ dp = &d->next;
+ div_set(d, a->r.min.x);
+
+ if(!a->next) {
+ d = getdiv(dp);
+ dp = &d->next;
+ div_set(d, a->r.max.x);
+ }
+ }
+ for(d = *dp; d; d = d->next)
+ unmapdiv(d);
+}
+
+/* Div Handlers */
+static void
+bdown_event(Window *w, XButtonEvent *e) {
+ Divide *d;
+
+ USED(e);
+
+ d = w->aux;
+ mouse_resizecol(d);
+}
+
+static void
+expose_event(Window *w, XExposeEvent *e) {
+ Divide *d;
+
+ USED(e);
+
+ d = w->aux;
+ drawdiv(d);
+}
+
+static Handlers handlers = {
+ .bdown = bdown_event,
+ .expose = expose_event,
+};
+
diff --git a/cmd/wmii/event.c b/cmd/wmii/event.c
@@ -10,8 +10,10 @@ void
dispatch_event(XEvent *e) {
Debug(DEvent)
printevent(e);
- if(handler[e->type])
+ if(e->type < nelem(handler) && handler[e->type])
handler[e->type](e);
+ else
+ xext_event(e);
}
#define handle(w, fn, ev) \
@@ -276,7 +278,7 @@ maprequest(XEvent *e) {
if(wa.override_redirect) {
/* Do I really want these? */
XSelectInput(display, ev->window,
- (StructureNotifyMask | PropertyChangeMask));
+ (StructureNotifyMask | PropertyChangeMask));
return;
}
if(!win2client(ev->window))
@@ -356,7 +358,5 @@ check_x_event(IxpConn *c) {
while(XPending(display)) {
XNextEvent(display, &ev);
dispatch_event(&ev);
- /* Hack to alleviate an apparant Xlib bug */
- XPending(display);
}
}
diff --git a/cmd/wmii/ewmh.c b/cmd/wmii/ewmh.c
@@ -17,22 +17,6 @@ Window *ewmhwin;
#define STATE(x) xatom(State(x))
#define TYPE(x) xatom(Type(x))
-static void
-senemessage(Window *w, char *name, char *value, long l2, long l3, long l4) {
- XClientMessageEvent e;
-
- e.type = ClientMessage;
- e.window = w->w;
- e.message_type = xatom(name);
- e.format = 32;
- e.data.l[0] = xatom(value);
- e.data.l[1] = xtime;
- e.data.l[2] = l2;
- e.data.l[3] = l3;
- e.data.l[4] = l4;
- sendevent(w, false, NoEventMask, (XEvent*)&e);
-}
-
void
ewmh_init(void) {
WinAttr wa;
@@ -143,7 +127,8 @@ ewmh_destroyclient(Client *c) {
e = &c->w.ewmh;
if(e->timer)
- ixp_unsettimer(&srv, e->timer);
+ if(!ixp_unsettimer(&srv, e->timer))
+ fprint(2, "Badness: %C: Can't unset timer\n", c);
}
static void
@@ -167,18 +152,21 @@ ewmh_pingclient(Client *c) {
if(e->ping)
return;
- senemessage(&c->w, "WM_PROTOCOLS", Net("WM_PING"), c->w.w, 0, 0);
+ sendmessage(&c->w, "WM_PROTOCOLS", Net("WM_PING"), c->w.w, 0, 0);
e->ping = xtime++;
e->timer = ixp_settimer(&srv, PingTime, pingtimeout, c);
}
-void
+int
ewmh_prop(Client *c, Atom a) {
if(a == NET("WM_WINDOW_TYPE"))
ewmh_getwintype(c);
else
if(a == NET("WM_STRUT_PARTIAL"))
ewmh_getstrut(c);
+ else
+ return 0;
+ return 1;
}
typedef struct Prop Prop;
@@ -336,7 +324,7 @@ ewmh_clientmessage(XClientMessageEvent *e) {
fullscreen(c, action);
else
if(l[i] == STATE("DEMANDS_ATTENTION"))
- client_seturgent(c, action, false);
+ client_seturgent(c, action, UrgClient);
}
return 1;
}else
@@ -415,7 +403,7 @@ ewmh_updatestate(Client *c) {
int i;
f = c->sel;
- if(f->view != screen->sel)
+ if(f == nil || f->view != screen->sel)
return;
i = 0;
diff --git a/cmd/wmii/float.c b/cmd/wmii/float.c
@@ -0,0 +1,144 @@
+/* Copyright ©2006-2008 Kris Maglione <fbsdaemon@gmail.com>
+ * See LICENSE file for license details.
+ */
+#include "dat.h"
+#include <sys/limits.h>
+#include "fns.h"
+
+static void float_placeframe(Frame*);
+
+void
+float_attach(Area *a, Frame *f) {
+
+ f->client->floating = true;
+
+ float_placeframe(f);
+ frame_insert(f, a->sel);
+
+ if(a->sel == nil)
+ area_setsel(a, f);
+}
+
+void
+float_detach(Frame *f) {
+ Frame *pr;
+ Area *a, *sel;
+ View *v;
+
+ v = f->view;
+ a = f->area;
+ sel = view_findarea(v, v->selcol, false);
+ pr = f->aprev;
+
+ frame_remove(f);
+
+ f->area = nil;
+ if(a->sel == f) {
+ if(!pr)
+ pr = a->frame;
+ a->sel = nil;
+ area_setsel(a, pr);
+ }
+
+ if(v->oldsel)
+ area_focus(v->oldsel);
+ else if(!a->frame)
+ if(sel->frame)
+ area_focus(sel);
+}
+
+static void
+rect_push(Vector_rect *vec, Rectangle r) {
+ Rectangle *rp;
+ int i;
+
+ for(i=0; i < vec->n; i++) {
+ rp = &vec->ary[i];
+ if(rect_contains_p(*rp, r))
+ return;
+ if(rect_contains_p(r, *rp)) {
+ *rp = r;
+ return;
+ }
+ }
+ vector_rpush(vec, r);
+}
+
+static void
+float_placeframe(Frame *f) {
+ static Vector_rect rvec, rvec2;
+ Vector_rect *vp, *vp2, *vptemp;
+ Rectangle *rp;
+ Rectangle r, fr;
+ Point dim, p;
+ Client *c;
+ Frame *ff;
+ Area *a;
+ long area, l;
+ int i;
+
+ a = f->area;
+ c = f->client;
+
+ if(c->trans)
+ return;
+ if(c->fullscreen || c->w.hints->position || starting) {
+ f->r = client_grav(c, c->r);
+ return;
+ }
+
+ dim.x = Dx(f->r);
+ dim.y = Dy(f->r);
+
+ rvec.n = 0;
+ rvec2.n = 0;
+ vp = &rvec;
+ vp2 = &rvec2;
+
+ /* Find all rectangles on the floating layer into which
+ * the new frame would fit. (Please ignore the man behind
+ * the curtain).
+ */
+ vector_rpush(vp, a->r);
+ for(ff=a->frame; ff; ff=ff->anext) {
+ fr = ff->r;
+ vp2->n = 0;
+ for(i=0; i < vp->n; i++) {
+ r = vp->ary[i];
+ if(!rect_intersect_p(fr, r)) {
+ rect_push(vp2, r);
+ continue;
+ }
+ if(r.min.x < fr.min.x && fr.min.x - r.min.x >= dim.x)
+ rect_push(vp2, Rect(r.min.x, r.min.y, fr.min.x, r.max.y));
+ if(r.max.x > fr.max.x && r.max.x - fr.max.x >= dim.x)
+ rect_push(vp2, Rect(fr.max.x, r.min.y, r.max.x, r.max.y));
+ if(r.min.y < fr.min.y && fr.min.y - r.min.y >= dim.y)
+ rect_push(vp2, Rect(r.min.x, r.min.y, r.max.x, fr.min.y));
+ if(r.max.y > fr.max.y && r.max.y - fr.max.y >= dim.y)
+ rect_push(vp2, Rect(r.min.x, fr.max.y, r.max.x, r.max.y));
+ }
+ vptemp = vp;
+ vp = vp2;
+ vp2 = vptemp;
+ }
+
+ if(vp->n == 0) {
+ p.x = random() % max(0, Dx(a->r) - dim.x);
+ p.y = random() % max(0, Dy(a->r) - dim.y);
+ }else {
+ area = LONG_MAX;
+ for(i=0; i < vp->n; i++) {
+ rp = &vp->ary[i];
+ l = Dx(*rp) * Dy(*rp);
+ if(l < area) {
+ area = l;
+ p = rp->min;
+ }
+ }
+ }
+
+ fr = rectsubpt(f->r, f->r.min);
+ f->r = rectaddpt(fr, p);
+}
+
diff --git a/cmd/wmii/fns.h b/cmd/wmii/fns.h
@@ -9,44 +9,6 @@
# pragma varargck type "r" void
#endif
-/* XXX: These don't belong here. */
-
-typedef struct Vector_long Vector_long;
-struct Vector_long {
- long* ary;
- long n;
- long size;
-};
-
-static void
-vector_linit(Vector_long *v) {
- memset(v, 0, sizeof *v);
-}
-
-static void
-vector_lfree(Vector_long *v) {
- free(v->ary);
- memset(v, 0, sizeof *v);
-}
-
-static void
-vector_lpush(Vector_long *v, long val) {
- if(v->n == v->size) {
- if(v->size == 0)
- v->size = 2;
- v->size <<= 2;
- v->ary = erealloc(v->ary, v->size * sizeof *v->ary);
- }
- v->ary[v->n++] = val;
-}
-
-static inline void
-__grr__(void) {
- vector_linit(nil);
- vector_lfree(nil);
- vector_lpush(nil, 0);
-}
-
/* area.c */
void area_attach(Area*, Frame*);
Area* area_create(View*, Area *pos, uint w);
@@ -74,6 +36,7 @@ void apply_tags(Client*, const char*);
void client_configure(Client*);
Client* client_create(XWindow, XWindowAttributes*);
void client_destroy(Client*);
+bool client_floats_p(Client*);
void client_focus(Client*);
void client_kill(Client*, bool);
void client_manage(Client*);
@@ -82,7 +45,7 @@ void client_prop(Client*, Atom);
void client_reparent(Client*, Window*, Point);
void client_resize(Client*, Rectangle);
void client_setcursor(Client*, Cursor);
-void client_seturgent(Client*, int urgent, bool write);
+void client_seturgent(Client*, bool, int);
void client_unmap(Client*, int state);
Frame* client_viewframe(Client *c, View *v);
char* clientname(Client*);
@@ -96,15 +59,19 @@ Client* win2client(XWindow);
Rectangle client_grav(Client*, Rectangle);
/* column.c */
-char* colmode2str(int);
-int str2colmode(const char*);
+char* colmode2str(uint);
void column_arrange(Area*, bool dirty);
+void column_attach(Area*, Frame*);
+void column_detach(Frame*);
+void column_insert(Area*, Frame*, Frame*);
Area* column_new(View*, Area *, uint);
+void column_remove(Frame*, bool);
void column_resize(Area*, int);
void column_resizeframe(Frame*, Rectangle*);
void div_draw(Divide*);
void div_set(Divide*, int x);
void div_update_all(void);
+int str2colmode(const char*);
/* event.c */
void check_x_event(IxpConn*);
@@ -122,7 +89,7 @@ void ewmh_getwintype(Client*);
void ewmh_init(void);
void ewmh_initclient(Client*);
void ewmh_pingclient(Client*);
-void ewmh_prop(Client*, Atom);
+int ewmh_prop(Client*, Atom);
long ewmh_protocols(Window*);
void ewmh_updateclient(Client*);
void ewmh_updateclientlist(void);
@@ -132,6 +99,10 @@ void ewmh_updatestate(Client*);
void ewmh_updateview(void);
void ewmh_updateviews(void);
+/* float.c */
+void float_attach(Area*, Frame*);
+void float_detach(Frame*);
+
/* frame.c */
Frame* frame_create(Client*, View*);
int frame_delta_h(void);
@@ -139,7 +110,7 @@ void frame_draw(Frame*);
void frame_draw_all(void);
void frame_focus(Frame*);
uint frame_idx(Frame*);
-void frame_insert(Frame *pos, Frame*);
+void frame_insert(Frame*, Frame *pos);
void frame_remove(Frame*);
void frame_resize(Frame*, Rectangle);
bool frame_restack(Frame*, Frame*);
@@ -167,10 +138,13 @@ void fs_write(Ixp9Req*);
void event(const char*, ...);
/* geom.c */
-Cursor quad_cursor(Align);
Align get_sticky(Rectangle src, Rectangle dst);
-bool rect_haspoint_p(Point, Rectangle);
+Cursor quad_cursor(Align);
Align quadrant(Rectangle, Point);
+bool rect_contains_p(Rectangle, Rectangle);
+bool rect_haspoint_p(Point, Rectangle);
+bool rect_intersect_p(Rectangle, Rectangle);
+Rectangle rect_intersection(Rectangle, Rectangle);
/* key.c */
void init_lock_keys(void);
@@ -194,7 +168,8 @@ char* msg_getword(IxpMsg*);
char* msg_parsecolors(IxpMsg*, CTuple*);
char* msg_selectarea(Area*, IxpMsg*);
char* msg_sendclient(View*, IxpMsg*, bool swap);
-char* root_readctl(void);
+char* readctl_root(void);
+char* readctl_view(View*);
Area* strarea(View*, const char*);
/* mouse.c */
@@ -208,8 +183,30 @@ void trim(char *str, const char *chars);
void update_rules(Rule**, const char*);
/* view.c */
+void view_arrange(View*);
+void view_attach(View*, Frame*);
+View* view_create(const char*);
+void view_destroy(View*);
+Area* view_findarea(View*, int, bool);
+void view_focus(WMScreen*, View*);
+bool view_fullscreen_p(View*);
+char* view_index(View*);
+uint view_newcolw(View*, int i);
+void view_restack(View*);
+void view_scale(View*, int w);
+Client* view_selclient(View*);
+void view_select(const char*);
+void client_setviews(Client*, char**);
+void view_update_all(void);
+Rectangle* view_rects(View*, uint *num, Frame *ignore);
/* utf.c */
char* toutf8(const char*);
char* toutf8n(const char*, size_t);
+/* xext.c */
+void randr_event(XEvent*);
+void randr_init(void);
+void xext_event(XEvent*);
+void xext_init(void);
+
diff --git a/cmd/wmii/frame.c b/cmd/wmii/frame.c
@@ -35,7 +35,8 @@ frame_create(Client *c, View *v) {
f->revert = f->r;
c->sel = f;
}
- f->collapsed = False;
+ f->collapsed = false;
+ f->oldarea = -1;
return f;
}
@@ -64,7 +65,7 @@ frame_remove(Frame *f) {
}
void
-frame_insert(Frame *pos, Frame *f) {
+frame_insert(Frame *f, Frame *pos) {
Area *a;
a = f->area;
@@ -138,13 +139,13 @@ bdown_event(Window *w, XButtonEvent *e) {
if((e->state & def.mod) == def.mod) {
switch(e->button) {
case Button1:
- mouse_resize(c, False, CENTER);
+ mouse_resize(c, false, Center);
focus(c, false);
frame_restack(f, nil);
focus(c, false); /* Blech */
break;
case Button3:
- mouse_resize(c, False, quadrant(f->r, Pt(e->x_root, e->y_root)));
+ mouse_resize(c, false, quadrant(f->r, Pt(e->x_root, e->y_root)));
frame_restack(f, nil);
focus(c, false);
break;
@@ -159,10 +160,10 @@ bdown_event(Window *w, XButtonEvent *e) {
if(frame_restack(f, nil))
view_restack(f->view);
else if(rect_haspoint_p(Pt(e->x, e->y), f->grabbox))
- mouse_resize(c, True, CENTER);
+ mouse_resize(c, true, Center);
else if(f->area->floating)
if(!e->subwindow && !rect_haspoint_p(Pt(e->x, e->y), f->titlebar))
- mouse_resize(c, False, quadrant(f->r, Pt(e->x_root, e->y_root)));
+ mouse_resize(c, false, quadrant(f->r, Pt(e->x_root, e->y_root)));
if(f->client != selclient())
focus(c, false);
@@ -433,6 +434,8 @@ frame_draw(Frame *f) {
if(f->view != screen->sel)
return;
+ if(f->area == nil) /* Blech. */
+ return;
if(f->client == screen->focus
|| f->client == selclient())
@@ -486,13 +489,34 @@ frame_draw(Frame *f) {
r.max.y = labelh(def.font);
if(f->client->floating)
r.max.x -= Dx(f->grabbox);
- w = drawstring(screen->ibuf, def.font, r, WEST,
+ w = drawstring(screen->ibuf, def.font, r, West,
f->client->name, col->fg);
+ if(f->area->floating) {
+ r.min.x = r.min.x + w + 10;
+ r.max.x = f->titlebar.max.x + 1;
+ r.min.y = f->grabbox.min.y;
+ r.max.y = f->grabbox.max.y;
+ border(screen->ibuf, r, 1, col->border);
+ }
+
+ /* Border increment gaps... */
+ r.min.y = f->crect.min.y;
+ r.min.x = max(1, f->crect.min.x - 1);
+ r.max.x = min(fr.max.x - 1, f->crect.max.x + 1);
+ r.max.y = min(fr.max.y - 1, f->crect.max.y + 1);
+ border(screen->ibuf, r, 1, col->border);
+
+ /* Why? Because some non-ICCCM-compliant apps feel the need to
+ * change the background properties of all of their ancestor windows
+ * in order to implement pseudo-transparency.
+ * What's more, the designers of X11 felt that it would be unfair to
+ * implementers to make it possible to detect, or forbid, such changes.
+ */
XSetWindowBackgroundPixmap(display, f->client->framewin->w, None);
copyimage(f->client->framewin, fr, screen->ibuf, ZP);
- XSync(display, False);
+ sync();
}
void
diff --git a/cmd/wmii/fs.c b/cmd/wmii/fs.c
@@ -679,7 +679,7 @@ fs_read(Ixp9Req *r) {
respond(r, nil);
return;
case FsFTctl:
- buf = view_ctl(f->p.view);
+ buf = readctl_view(f->p.view);
n = strlen(buf);
write_buf(r, buf, n);
respond(r, nil);
diff --git a/cmd/wmii/geom.c b/cmd/wmii/geom.c
@@ -10,6 +10,34 @@ rect_haspoint_p(Point pt, Rectangle r) {
&& (pt.y >= r.min.y) && (pt.y < r.max.y);
}
+bool
+rect_intersect_p(Rectangle r, Rectangle r2) {
+ return r.min.x <= r2.max.x
+ && r.max.x >= r2.min.x
+ && r.min.y <= r2.max.y
+ && r.max.y >= r2.min.y;
+}
+
+Rectangle
+rect_intersection(Rectangle r, Rectangle r2) {
+ Rectangle ret;
+
+ /* canonrect(ret) != ret if not intersection */
+ ret.min.x = max(r.min.x, r2.min.x);
+ ret.max.x = min(r.max.x, r2.max.x);
+ ret.min.y = max(r.min.y, r2.min.y);
+ ret.max.y = min(r.max.y, r2.max.y);
+ return ret;
+}
+
+bool
+rect_contains_p(Rectangle r, Rectangle r2) {
+ return r2.min.x >= r.min.x
+ && r2.max.x <= r.max.x
+ && r2.min.y >= r.min.y
+ && r2.max.y <= r.max.y;
+}
+
Align
quadrant(Rectangle r, Point pt) {
Align ret;
@@ -18,13 +46,13 @@ quadrant(Rectangle r, Point pt) {
ret = 0;
if(pt.x >= Dx(r) * .5)
- ret |= EAST;
+ ret |= East;
if(pt.x <= Dx(r) * .5)
- ret |= WEST;
+ ret |= West;
if(pt.y <= Dy(r) * .5)
- ret |= NORTH;
+ ret |= North;
if(pt.y >= Dy(r) * .5)
- ret |= SOUTH;
+ ret |= South;
return ret;
}
@@ -32,13 +60,13 @@ quadrant(Rectangle r, Point pt) {
Cursor
quad_cursor(Align align) {
switch(align) {
- case NEAST:
+ case NEast:
return cursor[CurNECorner];
- case NWEST:
+ case NWest:
return cursor[CurNWCorner];
- case SEAST:
+ case SEast:
return cursor[CurSECorner];
- case SWEST:
+ case SWest:
return cursor[CurSWCorner];
default:
return cursor[CurMove];
@@ -50,13 +78,13 @@ get_sticky(Rectangle src, Rectangle dst) {
Align stickycorner = 0;
if(src.min.x != dst.min.x && src.max.x == dst.max.x)
- stickycorner |= EAST;
+ stickycorner |= East;
else
- stickycorner |= WEST;
+ stickycorner |= West;
if(src.min.y != dst.min.y && src.max.y == dst.max.y)
- stickycorner |= SOUTH;
+ stickycorner |= South;
else
- stickycorner |= NORTH;
+ stickycorner |= North;
return stickycorner;
}
diff --git a/cmd/wmii/main.c b/cmd/wmii/main.c
@@ -133,7 +133,8 @@ init_ns(void) {
if(getuid() != st.st_uid)
fatal("ns_path '%s' exists but is not owned by you", ns_path);
if(st.st_mode & 077)
- fatal("ns_path '%s' exists, but has group or world permissions", ns_path);
+ if(chmod(ns_path, st.st_mode & ~077))
+ fatal("ns_path '%s' exists, but has group or world permissions", ns_path);
}
static void
@@ -383,6 +384,9 @@ main(int argc, char *argv[]) {
case 'r':
wmiirc = EARGF(usage());
break;
+ case 'v':
+ print("%s", version);
+ exit(0);
default:
usage();
break;
@@ -424,6 +428,7 @@ main(int argc, char *argv[]) {
init_cursors();
init_lock_keys();
ewmh_init();
+ xext_init();
srv.preselect = check_preselect;
ixp_listen(&srv, sock, &p9srv, serve_9pcon, nil);
@@ -463,11 +468,11 @@ main(int argc, char *argv[]) {
screen->focus = nil;
setfocus(screen->barwin, RevertToParent);
+ view_select("1");
scan_wins();
starting = false;
- view_select("nil");
view_update_all();
ewmh_updateviews();
diff --git a/cmd/wmii/message.c b/cmd/wmii/message.c
@@ -156,13 +156,13 @@ msg_getword(IxpMsg *m) {
Rune r;
int n;
- eatrunes(m, isspacerune, 1);
+ eatrunes(m, isspacerune, true);
ret = m->pos;
- eatrunes(m, isspacerune, 0);
+ eatrunes(m, isspacerune, false);
n = chartorune(&r, m->pos);
*m->pos = '\0';
m->pos += n;
- eatrunes(m, isspacerune, 1);
+ eatrunes(m, isspacerune, true);
if(ret == m->end)
return nil;
@@ -285,7 +285,7 @@ message_client(Client *c, IxpMsg *m) {
i = gettoggle(m);
if(i == -1)
return Ebadusage;
- client_seturgent(c, i, True);
+ client_seturgent(c, i, UrgManager);
break;
default:
return Ebadcmd;
@@ -391,17 +391,55 @@ message_view(View *v, IxpMsg *m) {
case LSELECT:
return msg_selectarea(v->sel, m);
case LSEND:
- return msg_sendclient(v, m, 0);
+ return msg_sendclient(v, m, false);
case LSWAP:
- return msg_sendclient(v, m, 1);
+ return msg_sendclient(v, m, true);
default:
return Ebadcmd;
}
/* not reached */
}
-char *
-parse_colors(IxpMsg *m, CTuple *col) {
+static void
+printdebug(void) {
+ int i, j;
+
+ for(i=0, j=0; i < nelem(debugtab); i++)
+ Debug(1<<i) {
+ if(j++ > 0)
+ bufprint(" ");
+ bufprint("%s", debugtab[i]);
+ }
+}
+
+static char*
+msg_debug(IxpMsg *m) {
+ char *opt;
+ int d;
+ char add;
+
+ bufclear();
+ while((opt = msg_getword(m))) {
+ add = '+';
+ if(opt[0] == '+' || opt[0] == '-')
+ add = *opt++;
+ d = getdebug(opt);
+ if(d == -1) {
+ bufprint(", %s", opt);
+ continue;
+ }
+ if(add == '+')
+ debug |= 1<<d;
+ else
+ debug &= ~(1<<d);
+ }
+ if(buffer[0] != '\0')
+ return sxprint("Bad debug options: %s", buffer+2);
+ return nil;
+}
+
+char*
+msg_parsecolors(IxpMsg *m, CTuple *col) {
static char Ebad[] = "bad color string";
Rune r;
char c, *p;
@@ -431,7 +469,7 @@ parse_colors(IxpMsg *m, CTuple *col) {
*p = c;
m->pos = p;
- eatrunes(m, isspacerune, 1);
+ eatrunes(m, isspacerune, true);
return nil;
}
@@ -596,10 +634,10 @@ msg_sendclient(View *v, IxpMsg *m, bool swap) {
case LTOGGLE:
if(!a->floating)
to = v->area;
- else if(c->revert && !c->revert->floating)
- to = c->revert;
+ else if(f->column)
+ to = view_findarea(v, f->column, true);
else
- to = v->area->next;
+ to = view_findarea(v, v->selcol, true);
break;
default:
if(!getulong(s, &i) || i == 0)
@@ -657,7 +695,7 @@ msg_sendframe(Frame *f, int sym, bool swap) {
frame_swap(f, fp);
}else {
frame_remove(f);
- frame_insert(fp, f);
+ frame_insert(f, fp);
}
view_arrange(f->view);
diff --git a/cmd/wmii/mouse.c b/cmd/wmii/mouse.c
@@ -5,6 +5,8 @@
#include <assert.h>
#include "fns.h"
+/* Here be dragons. */
+
enum {
ButtonMask =
ButtonPressMask | ButtonReleaseMask,
@@ -17,15 +19,16 @@ static Handlers handlers;
enum { OHoriz, OVert };
typedef struct Framewin Framewin;
struct Framewin {
- Window *w;
- Frame *f;
- Frame *fp;
- Rectangle fr;
- Area *ra;
- Rectangle gb;
- Point pt;
- int or;
- int n;
+ /* Todo... give these better names. */
+ Window* w;
+ Rectangle grabbox;
+ Rectangle fprev_r;
+ Frame* fprev;
+ Frame* f;
+ Area* ra;
+ Point pt;
+ int orientation;
+ int xy;
};
static Rectangle
@@ -34,13 +37,13 @@ framerect(Framewin *f) {
Point p;
r.min = ZP;
- if(f->or == OHoriz) {
- r.max.x = f->n;
- r.max.y = f->gb.max.y + f->gb.min.y;
+ if(f->orientation == OHoriz) {
+ r.max.x = f->xy;
+ r.max.y = f->grabbox.max.y + f->grabbox.min.y;
r = rectsubpt(r, Pt(0, Dy(r)/2));
}else {
- r.max.x = f->gb.max.x + f->gb.min.x;
- r.max.y = f->n;
+ r.max.x = f->grabbox.max.x + f->grabbox.min.x;
+ r.max.y = f->xy;
r = rectsubpt(r, Pt(Dx(r)/2, 0));
}
r = rectaddpt(r, f->pt);
@@ -54,14 +57,14 @@ framerect(Framewin *f) {
}
static void
-frameadjust(Framewin *f, Point pt, int or, int n) {
- f->or = or;
- f->n = n;
+frameadjust(Framewin *f, Point pt, int orientation, int xy) {
+ f->orientation = orientation;
+ f->xy = xy;
f->pt = pt;
}
static Framewin*
-framewin(Frame *f, Point pt, int or, int n) {
+framewin(Frame *f, Point pt, int orientation, int n) {
WinAttr wa;
Framewin *fw;
@@ -73,8 +76,8 @@ framewin(Frame *f, Point pt, int or, int n) {
sethandler(fw->w, &handlers);
fw->f = f;
- fw->gb = f->grabbox;
- frameadjust(fw, pt, or, n);
+ fw->grabbox = f->grabbox;
+ frameadjust(fw, pt, orientation, n);
reshapewin(fw->w, framerect(fw));
mapwin(fw->w);
@@ -105,8 +108,8 @@ expose_event(Window *w, XExposeEvent *e) {
r = rectsubpt(w->r, w->r.min);
fill(buf, r, c->bg);
border(buf, r, 1, c->border);
- border(buf, f->gb, 1, c->border);
- border(buf, insetrect(f->gb, -f->gb.min.x), 1, c->border);
+ border(buf, f->grabbox, 1, c->border);
+ border(buf, insetrect(f->grabbox, -f->grabbox.min.x), 1, c->border);
copyimage(w, r, buf, ZP);
}
@@ -117,8 +120,8 @@ static Handlers handlers = {
static int
_vsnap(Framewin *f, int y) {
- if(abs(f->n - y) < Dy(f->w->r)) {
- f->n = y;
+ if(abs(f->xy - y) < Dy(f->w->r)) {
+ f->xy = y;
return 1;
}
return 0;
@@ -144,38 +147,38 @@ vplace(Framewin *fw, Point pt) {
r = fw->w->r;
hr = Dy(r)/2;
- fw->n = pt.y;
+ fw->xy = pt.y;
for(f = a->frame; f->anext; f = f->anext)
if(pt.y < f->r.max.y)
break;
if(!f->collapsed) {
- fw->fp = f;
- fw->fr = fw->fp->r;
+ fw->fprev = f;
+ fw->fprev_r = f->r;
if(f == fw->f) {
- fw->fp = f->aprev;
- fw->fr.max = f->r.max;
+ fw->fprev = f->aprev;
+ fw->fprev_r.max = f->r.max;
if(_vsnap(fw, f->r.min.y+hr))
goto done;
}
if(_vsnap(fw, f->r.max.y - hr)) {
- fw->fr.min.y = f->r.max.y - labelh(def.font);
+ fw->fprev_r.min.y = f->r.max.y - labelh(def.font);
goto done;
}
if(_vsnap(fw, f->r.min.y+Dy(r)+hr)) {
- fw->fr.min.y = f->r.min.y + labelh(def.font);
+ fw->fprev_r.min.y = f->r.min.y + labelh(def.font);
goto done;
}
if(f->aprev == nil || f->aprev->collapsed)
_vsnap(fw, f->r.min.y);
else if(_vsnap(fw, f->r.min.y-hr))
- fw->fp = f->aprev;
- fw->fr.min.y = pt.y - hr;
- if(fw->fp && fw->fp->anext == fw->f)
- fw->fr.max = fw->f->r.max;
+ fw->fprev = f->aprev;
+ fw->fprev_r.min.y = pt.y - hr;
+ if(fw->fprev && fw->fprev->anext == fw->f)
+ fw->fprev_r.max = fw->f->r.max;
goto done;
}
@@ -191,7 +194,7 @@ vplace(Framewin *fw, Point pt) {
done:
pt.x = a->r.min.x;
- pt.y = fw->n;
+ pt.y = fw->xy;
frameadjust(fw, pt, OHoriz, Dx(a->r));
reshapewin(fw->w, framerect(fw));
}
@@ -202,8 +205,8 @@ hplace(Framewin *fw, Point pt) {
View *v;
int minw;
- minw = Dx(screen->r)/NCOL;
v = screen->sel;
+ minw = Dx(v->r)/NCOL;
for(a = v->area->next; a->next; a = a->next)
if(pt.x < a->r.max.x)
@@ -231,7 +234,7 @@ do_managed_move(Client *c) {
XEvent ev;
Framewin *fw;
Window *cwin;
- Frame *f;
+ Frame *f, *fprev, *fnext;
Point pt, pt2;
int y;
@@ -245,7 +248,7 @@ do_managed_move(Client *c) {
fw = framewin(f, pt2, OHoriz, Dx(f->area->r));
r = screen->r;
- r.min.y += fw->gb.min.y + Dy(fw->gb)/2;
+ r.min.y += fw->grabbox.min.y + Dy(fw->grabbox)/2;
r.max.y = r.min.y + 1;
cwin = createwindow(&scr.root, r, 0, InputOnly, &wa, 0);
mapwin(cwin);
@@ -274,34 +277,39 @@ horiz:
switch(ev.xbutton.button) {
case 1:
/* TODO: Fix... Tangled, broken mess. */
- if((f->anext) && (!f->aprev || (fw->fp != f->aprev && fw->fp != f->aprev->aprev))) {
- f->anext->r.min.y = f->r.min.y;
- frame_resize(f->anext, f->anext->r);
+ fprev = f->aprev;
+ fnext = f->anext;
+ column_remove(f, false);
+ if(fnext
+ && (!fprev || (fw->fprev != fprev)
+ && (fw->fprev != fprev->aprev))) {
+ fnext->r.min.y = f->r.min.y;
+ frame_resize(fnext, fnext->r);
}
- else if(f->aprev) {
- if(fw->fp == f->aprev->aprev) {
- fw->fp = f->aprev->aprev;
- f->aprev->r = f->r;
+ else if(fprev) {
+ if(fw->fprev == fprev->aprev) {
+ fw->fprev = fprev->aprev;
+ fprev->r = f->r;
}else
- f->aprev->r.max.y = f->r.max.y;
- frame_resize(f->aprev, f->aprev->r);
+ fprev->r.max.y = f->r.max.y;
+ frame_resize(fprev, fprev->r);
}
- frame_remove(f);
- f->area = fw->ra;
- frame_insert(fw->fp, f);
+ column_insert(fw->ra, f, fw->fprev);
+ r = fw->fprev_r;
if(f->aprev) {
f->aprev->r.max.y = fw->fr.min.y;
frame_resize(f->aprev, f->aprev->r);
- }
- else
- fw->fr.min.y = f->area->r.min.y;
+ }else
+ r.min.y = f->area->r.min.y;
+
if(f->anext)
- fw->fr.max.y = f->anext->r.min.y;
+ r.max.y = f->anext->r.min.y;
else
- fw->fr.max.y = f->area->r.max.y;
- frame_resize(f, fw->fr);
+ r.max.y = f->area->r.max.y;
+
+ frame_resize(f, fw->fprev_r);
view_arrange(f->view);
goto done;
@@ -341,6 +349,7 @@ vert:
if(fw->ra) {
fw->ra = column_new(f->view, fw->ra, 0);
area_moveto(fw->ra, f);
+ view_arrange(f->view); /* I hate this. */
}
goto done;
case 2:
@@ -384,19 +393,19 @@ mouse_resizecolframe(Frame *f, Align align) {
Rectangle r;
Point pt, min;
- assert((align&(EAST|WEST)) != (EAST|WEST));
- assert((align&(NORTH|SOUTH)) != (NORTH|SOUTH));
+ assert((align&(East|West)) != (East|West));
+ assert((align&(North|South)) != (North|South));
v = screen->sel;
for(a = v->area->next, d = divs; a; a = a->next, d = d->next)
if(a == f->area) break;
- if(align&EAST)
+ if(align&East)
d = d->next;
- min.x = Dx(screen->r)/NCOL;
- min.y = frame_delta_h() + labelh(def.font);
- if(align&NORTH) {
+ min.x = Dx(v->r)/NCOL;
+ min.y = /*frame_delta_h() +*/ labelh(def.font);
+ if(align&North) {
if(f->aprev) {
r.min.y = f->aprev->r.min.y + min.y;
r.max.y = f->r.max.y - min.y;
@@ -413,7 +422,7 @@ mouse_resizecolframe(Frame *f, Align align) {
r.min.y = r.max.y - 1;
}
}
- if(align&WEST) {
+ if(align&West) {
if(a->prev != v->area) {
r.min.x = a->prev->r.min.x + min.x;
r.max.x = a->r.max.x - min.x;
@@ -435,7 +444,7 @@ mouse_resizecolframe(Frame *f, Align align) {
mapwin(cwin);
r = f->r;
- if(align&NORTH)
+ if(align&North)
r.min.y--;
else
r.min.y = r.max.y - 1;
@@ -446,8 +455,8 @@ mouse_resizecolframe(Frame *f, Align align) {
if(!grabpointer(&scr.root, cwin, cursor[CurSizing], MouseMask))
goto done;
- pt.x = ((align&WEST) ? f->r.min.x : f->r.max.x);
- pt.y = ((align&NORTH) ? f->r.min.y : f->r.max.y);
+ pt.x = ((align&West) ? f->r.min.x : f->r.max.x);
+ pt.y = ((align&North) ? f->r.min.y : f->r.max.y);
warppointer(pt);
for(;;) {
@@ -462,11 +471,11 @@ mouse_resizecolframe(Frame *f, Align align) {
pt.x = ev.xmotion.x_root;
pt.y = ev.xmotion.y_root;
- if(align&WEST)
+ if(align&West)
r.min.x = pt.x;
else
r.max.x = pt.x;
- r.min.y = ((align&SOUTH) ? pt.y : pt.y-1);
+ r.min.y = ((align&South) ? pt.y : pt.y-1);
r.max.y = r.min.y+2;
div_set(d, pt.x);
@@ -474,22 +483,22 @@ mouse_resizecolframe(Frame *f, Align align) {
break;
case ButtonRelease:
r = f->r;
- if(align&WEST)
+ if(align&West)
r.min.x = pt.x;
else
r.max.x = pt.x;
- if(align&NORTH)
+ if(align&North)
r.min.y = pt.y;
else
r.max.y = pt.y;
column_resizeframe(f, &r);
/* XXX: Magic number... */
- if(align&WEST)
+ if(align&West)
pt.x = f->r.min.x + 4;
else
pt.x = f->r.max.x - 4;
- if(align&NORTH)
+ if(align&North)
pt.y = f->r.min.y + 4;
else
pt.y = f->r.max.y - 4;
@@ -526,7 +535,7 @@ mouse_resizecol(Divide *d) {
pt = querypointer(&scr.root);
- minw = Dx(screen->r)/NCOL;
+ minw = Dx(v->r)/NCOL;
r.min.x = a->r.min.x + minw;
r.max.x = a->next->r.max.x - minw;
r.min.y = pt.y;
@@ -564,26 +573,26 @@ static void
rect_morph(Rectangle *r, Point d, Align *mask) {
int n;
- if(*mask & NORTH)
+ if(*mask & North)
r->min.y += d.y;
- if(*mask & WEST)
+ if(*mask & West)
r->min.x += d.x;
- if(*mask & SOUTH)
+ if(*mask & South)
r->max.y += d.y;
- if(*mask & EAST)
+ if(*mask & East)
r->max.x += d.x;
if(r->min.x > r->max.x) {
n = r->min.x;
r->min.x = r->max.x;
r->max.x = n;
- *mask ^= EAST|WEST;
+ *mask ^= East|West;
}
if(r->min.y > r->max.y) {
n = r->min.y;
r->min.y = r->max.y;
r->max.y = n;
- *mask ^= NORTH|SOUTH;
+ *mask ^= North|South;
}
}
@@ -639,24 +648,24 @@ snap_rect(Rectangle *rects, int num, Rectangle *r, Align *mask, int snap) {
d.x = snap+1;
d.y = snap+1;
- if(*mask&NORTH)
+ if(*mask&North)
d.y = snap_hline(rects, num, d.y, r, r->min.y);
- if(*mask&SOUTH)
+ if(*mask&South)
d.y = snap_hline(rects, num, d.y, r, r->max.y);
- if(*mask&EAST)
+ if(*mask&East)
d.x = snap_vline(rects, num, d.x, r, r->max.x);
- if(*mask&WEST)
+ if(*mask&West)
d.x = snap_vline(rects, num, d.x, r, r->min.x);
- ret = CENTER;
+ ret = Center;
if(abs(d.x) <= snap)
- ret ^= EAST|WEST;
+ ret ^= East|West;
else
d.x = 0;
if(abs(d.y) <= snap)
- ret ^= NORTH|SOUTH;
+ ret ^= North|South;
else
d.y = 0;
@@ -666,7 +675,7 @@ snap_rect(Rectangle *rects, int num, Rectangle *r, Align *mask, int snap) {
/* Grumble... Messy... TODO: Rewrite. */
void
-do_mouse_resize(Client *c, Bool opaque, Align align) {
+mouse_resize(Client *c, bool grabbox, Align align) {
XEvent ev;
Rectangle *rects;
Rectangle frect, origin;
@@ -679,8 +688,11 @@ do_mouse_resize(Client *c, Bool opaque, Align align) {
f = c->sel;
+ if(f->client->fullscreen)
+ return;
+
if(!f->area->floating) {
- if(align==CENTER)
+ if(align==Center)
do_managed_move(c);
else
mouse_resizecolframe(f, align);
@@ -692,7 +704,7 @@ do_mouse_resize(Client *c, Bool opaque, Align align) {
rects = view_rects(f->area->view, &num, c->frame);
cur = quad_cursor(align);
- if((align==CENTER) && !opaque)
+ if((align==Center) && !grabbox)
cur = cursor[CurSizing];
pt = querypointer(c->framewin);
@@ -707,21 +719,17 @@ do_mouse_resize(Client *c, Bool opaque, Align align) {
hr = subpt(frect.max, frect.min);
hr = divpt(hr, Pt(2, 2));
- if(align != CENTER) {
+ if(align != Center) {
d = hr;
- if(align&NORTH) d.y -= hr.y;
- if(align&SOUTH) d.y += hr.y;
- if(align&EAST) d.x += hr.x;
- if(align&WEST) d.x -= hr.x;
+ if(align&North) d.y -= hr.y;
+ if(align&South) d.y += hr.y;
+ if(align&East) d.x += hr.x;
+ if(align&West) d.x -= hr.x;
pt = addpt(d, f->r.min);
warppointer(pt);
}
- else if(f->client->fullscreen) {
- ungrabpointer();
- return;
- }
- else if(!opaque) {
+ else if(!grabbox) {
hrx = (double)(Dx(screen->r) + Dx(frect) - 2 * labelh(def.font))
/ Dx(screen->r);
hry = (double)(Dy(screen->r) + Dy(frect) - 3 * labelh(def.font))
@@ -748,7 +756,7 @@ do_mouse_resize(Client *c, Bool opaque, Align align) {
d.x = ev.xmotion.x_root;
d.y = ev.xmotion.y_root;
- if(align == CENTER && !opaque) {
+ if(align == Center && !grabbox) {
SET(hrx);
SET(hry);
d.x = (d.x * hrx) - pt.x;
@@ -772,7 +780,7 @@ do_mouse_resize(Client *c, Bool opaque, Align align) {
case ButtonRelease:
client_resize(c, frect);
- if(!opaque) {
+ if(!grabbox) {
pt = translate(c->framewin, &scr.root,
Pt(Dx(frect)*rx, Dy(frect)*ry));
if(pt.y > screen->brect.min.y)
diff --git a/cmd/wmii/rule.c b/cmd/wmii/rule.c
@@ -6,34 +6,40 @@
#include <assert.h>
#include "fns.h"
-/* basic rule matching language /regex/ -> value
- * regex might contain POSIX regex syntax defined in regex(3) */
-enum {
- IGNORE,
- REGEX,
- VALUE
-};
-
void
trim(char *str, const char *chars) {
const char *cp;
char *p, *q;
char c;
- for(cp = chars; (c = *cp); cp++) {
- q = str;
- for(p = q; *p; p++)
- if(*p != c)
- *q++ = *p;
- *q = '\0';
+ q = str;
+ for(p = str; *p; p++) {
+ for(cp = chars; (c = *cp); cp++)
+ if(*p == c)
+ goto nextchar;
+ *q++ = *p;
+ nextchar:
+ continue;
}
+ *q = '\0';
}
+/* XXX: I hate this. --KM */
void
update_rules(Rule **rule, const char *data) {
- int state = IGNORE;
+ /* basic rule matching language /regex/ -> value
+ * regex might contain POSIX regex syntax defined in regex(3) */
+ enum {
+ IGNORE,
+ REGEX,
+ VALUE,
+ COMMENT,
+ };
+ int state;
Rule *rul;
char regex[256], value[256];
+ char *regex_end = regex + sizeof(regex) - 1;
+ char *value_end = value + sizeof(value) - 1;
char *r, *v;
const char *p;
@@ -47,42 +53,49 @@ update_rules(Rule **rule, const char *data) {
free(rul->regex);
free(rul);
}
- for(p = data; *p; p++)
+ state = IGNORE;
+ for(p = data; (c = *p); p++)
switch(state) {
case IGNORE:
- if(*p == '/') {
+ if(c == '#')
+ state = COMMENT;
+ else if(c == '/') {
r = regex;
state = REGEX;
}
- else if(*p == '>') {
+ else if(c == '>') {
value[0] = 0;
v = value;
state = VALUE;
}
break;
case REGEX:
- if(*p == '/') {
+ if(c == '\\' && p[1] == '/')
+ p++;
+ else if(c == '/') {
*r = 0;
state = IGNORE;
}
- else
- *r++ = *p;
+ if(r < regex_end)
+ *r++ = c;
break;
case VALUE:
- if(*p == '\n' || *p == 0) {
- *rule = emallocz(sizeof(Rule));
+ if(c == '\n' || c == '#' || c == 0) {
*v = 0;
trim(value, " \t/");
+ *rule = emallocz(sizeof *rule);
(*rule)->regex = regcomp(regex);
if((*rule)->regex) {
utflcpy((*rule)->value, value, sizeof(rul->value));
rule = &(*rule)->next;
- }
- else free(*rule);
+ }else
+ free(*rule);
state = IGNORE;
+ if(c == '#')
+ state = COMMENT;
}
- else
- *v++ = *p;
+ else if(v < value_end)
+ *v++ = c;
break;
default: /* can't happen */
die("invalid state");
diff --git a/cmd/wmii/view.c b/cmd/wmii/view.c
@@ -51,6 +51,8 @@ view_create(const char *name) {
v = emallocz(sizeof(View));
v->id = id++;
+ v->r = screen->r;
+ v->r.max.y = screen->barwin->r.min.y;
utflcpy(v->name, name, sizeof(v->name));
@@ -99,6 +101,16 @@ view_destroy(View *v) {
ewmh_updateviews();
}
+Area*
+view_findarea(View *v, int idx, bool create) {
+ Area *a;
+
+ for(a=v->area->next; a && --idx > 0; a=a->next)
+ if(create && a->next == nil)
+ return area_create(v, a, 0);
+ return a;
+}
+
static void
update_frame_selectors(View *v) {
Area *a;
@@ -111,8 +123,10 @@ update_frame_selectors(View *v) {
void
view_focus(WMScreen *s, View *v) {
- Frame *f;
Client *c;
+ Frame *f;
+ Area *a;
+ bool fscrn;
USED(s);
@@ -121,6 +135,21 @@ view_focus(WMScreen *s, View *v) {
_view_select(v);
update_frame_selectors(v);
div_update_all();
+ fscrn = false;
+ for(a=v->area; a; a=a->next)
+ for(f=a->frame; f; f=f->anext)
+ if(f->client->fullscreen) {
+ fscrn = true;
+ if(!f->area->floating) {
+ f->oldr = f->revert;
+ f->oldarea = area_idx(f->area);
+ area_moveto(v->area, f);
+ area_setsel(v->area, f);
+ }else if(f->oldarea == -1) {
+ f->oldr = f->r; /* XXX: oldr */
+ f->oldarea = 0;
+ }
+ }
for(c=client; c; c=c->next)
if((f = c->sel)) {
if(f->view == v)
@@ -133,9 +162,12 @@ view_focus(WMScreen *s, View *v) {
ewmh_updateclient(c);
}
- restack_view(v);
- focus_area(v->sel);
- draw_frames();
+ view_restack(v);
+ if(fscrn)
+ area_focus(v->area);
+ else
+ area_focus(v->sel);
+ frame_draw_all();
sync();
XUngrabServer(display);
@@ -165,15 +197,11 @@ view_attach(View *v, Frame *f) {
Area *a;
c = f->client;
- c->revert = nil;
a = v->sel;
- if(c->trans || c->floating || c->fixedsize
- || c->titleless || c->borderless || c->fullscreen
- || (c->w.ewmh.type & (TypeDialog|TypeSplash|TypeDock)))
+ if(client_floats_p(c))
a = v->area;
- else if(c->group && c->group->client
- && (ff = client_viewframe(c->group->client, v)))
+ else if((ff = client_groupframe(c, v)))
a = ff->area;
else if(starting && v->sel->floating)
a = v->area->next;
@@ -228,7 +256,7 @@ view_scale(View *v, int w) {
float scale;
int wdiff, dx;
- minwidth = Dx(screen->r)/NCOL;
+ minwidth = Dx(v->r)/NCOL;
if(!v->area->next)
return;
@@ -278,7 +306,7 @@ view_arrange(View *v) {
if(!v->area->next)
return;
- view_scale(v, Dx(screen->r));
+ view_scale(v, Dx(v->r));
xoff = 0;
for(a=v->area->next; a; a=a->next) {
a->r.min.x = xoff;
@@ -314,83 +342,20 @@ view_rects(View *v, uint *num, Frame *ignore) {
return result;
}
-char*
-view_index(View *v) {
- Rectangle *r;
- Frame *f;
- Area *a;
- int i;
-
- bufclear();
- for((a=v->area), (i=0); a; (a=a->next), i++) {
- if(a->floating)
- bufprint("# ~ %d %d\n", Dx(a->r), Dy(a->r));
- else
- bufprint("# %d %d %d\n", i, a->r.min.x, Dx(a->r));
-
- for(f=a->frame; f; f=f->anext) {
- r = &f->r;
- if(a->floating)
- bufprint("~ %C %d %d %d %d %s\n",
- f->client,
- r->min.x, r->min.y,
- Dx(*r), Dy(*r),
- f->client->props);
- else
- bufprint("%d %C %d %d %s\n",
- i, f->client,
- r->min.y, Dy(*r),
- f->client->props);
- }
- }
- return buffer;
-}
-
-char*
-view_ctl(View *v) {
- Area *a;
- uint i;
-
- bufclear();
- bufprint("%s\n", v->name);
-
- /* select <area>[ <frame>] */
- bufprint("select %s", area_name(v->sel));
- if(v->sel->sel)
- bufprint(" %d", frame_idx(v->sel->sel));
- bufprint("\n");
-
- /* select client <client> */
- if(v->sel->sel)
- bufprint("select client %C\n", v->sel->sel->client);
-
- for(a = v->area->next, i = 1; a; a = a->next, i++)
- bufprint("colmode %d %s\n", i, colmode2str(a->mode));
- return buffer;
-}
-
void
view_update_all(void) {
View *n, *v, *old;
- int found;
old = screen->sel;
for(v=view; v; v=v->next)
update_frame_selectors(v);
- found = 0;
for(v=view; v; v=n) {
n=v->next;
- if(v != old) {
- if(empty_p(v))
- view_destroy(v);
- else
- found++;
- }
+ if(v != old && empty_p(v))
+ view_destroy(v);
}
- if(found && !strcmp(old->name, "nil") && empty_p(old))
- view_destroy(old);
view_focus(screen, screen->sel);
}
@@ -409,9 +374,41 @@ view_newcolw(View *v, int num) {
n = tokenize(toks, 16, buf, '+');
if(num < n)
if(getulong(toks[num], &n))
- return Dx(screen->r) * (n / 100.0);
+ return Dx(v->r) * (n / 100.0);
break;
}
return 0;
}
+char*
+view_index(View *v) {
+ Rectangle *r;
+ Frame *f;
+ Area *a;
+ int i;
+
+ bufclear();
+ for((a=v->area), (i=0); a; (a=a->next), i++) {
+ if(a->floating)
+ bufprint("# ~ %d %d\n", Dx(a->r), Dy(a->r));
+ else
+ bufprint("# %d %d %d\n", i, a->r.min.x, Dx(a->r));
+
+ for(f=a->frame; f; f=f->anext) {
+ r = &f->r;
+ if(a->floating)
+ bufprint("~ %C %d %d %d %d %s\n",
+ f->client,
+ r->min.x, r->min.y,
+ Dx(*r), Dy(*r),
+ f->client->props);
+ else
+ bufprint("%d %C %d %d %s\n",
+ i, f->client,
+ r->min.y, Dy(*r),
+ f->client->props);
+ }
+ }
+ return buffer;
+}
+
diff --git a/cmd/wmii/x11.c b/cmd/wmii/x11.c
@@ -8,8 +8,6 @@
#include "dat.h"
#include <assert.h>
#include <math.h>
-#include <stdlib.h>
-#include <string.h>
#include <unistd.h>
#include <bio.h>
#include "fns.h"
@@ -31,6 +29,7 @@ static MapEnt* wbucket[137];
static MapEnt* abucket[137];
+/* Rectangles/Points */
XRectangle
XRect(Rectangle r) {
XRectangle xr;
@@ -344,6 +343,7 @@ winprotocols(Window *w) {
/* Shape */
void
setshapemask(Window *dst, Image *src, Point pt) {
+ /* Assumes that we have the shape extension... */
XShapeCombineMask (display, dst->w,
ShapeBounding, pt.x, pt.y, src->image, ShapeSet);
}
@@ -454,7 +454,7 @@ drawstring(Image *dst, Font *font,
len += min(shortened, 3);
switch (align) {
- case EAST:
+ case East:
x = r.max.x - (w + (font->height / 2));
break;
default:
@@ -601,6 +601,22 @@ xatom(char *name) {
}
void
+sendmessage(Window *w, char *name, char *value, long l2, long l3, long l4) {
+ XClientMessageEvent e;
+
+ e.type = ClientMessage;
+ e.window = w->w;
+ e.message_type = xatom(name);
+ e.format = 32;
+ e.data.l[0] = xatom(value);
+ e.data.l[1] = xtime;
+ e.data.l[2] = l2;
+ e.data.l[3] = l3;
+ e.data.l[4] = l4;
+ sendevent(w, false, NoEventMask, (XEvent*)&e);
+}
+
+void
sendevent(Window *w, bool propegate, long mask, XEvent *e) {
XSendEvent(display, w->w, propegate, mask, e);
}
@@ -836,6 +852,7 @@ void
sethints(Window *w) {
enum { MaxInt = ((uint)(1<<(8*sizeof(int)-1))-1) };
XSizeHints xs;
+ XWMHints *wmh;
WinHints *h;
Point p;
long size;
@@ -849,6 +866,13 @@ sethints(Window *w) {
h->max = Pt(MaxInt, MaxInt);
h->inc = Pt(1,1);
+ wmh = XGetWMHints(display, w->w);
+ if(wmh) {
+ if(wmh->flags&WindowGroupHint)
+ h->group = wmh->window_group;
+ free(wmh);
+ }
+
if(!XGetWMNormalHints(display, w->w, &xs, &size))
return;
@@ -897,7 +921,9 @@ sethints(Window *w) {
case WestGravity:
p.y = 1;
break;
- case SouthEastGravity: case SouthGravity: case SouthWestGravity:
+ case SouthEastGravity:
+ case SouthGravity:
+ case SouthWestGravity:
p.y = 2;
break;
}
@@ -907,7 +933,9 @@ sethints(Window *w) {
case SouthGravity:
p.x = 1;
break;
- case NorthEastGravity: case EastGravity: case SouthEastGravity:
+ case NorthEastGravity:
+ case EastGravity:
+ case SouthEastGravity:
p.x = 2;
break;
}
diff --git a/cmd/wmii/xext.c b/cmd/wmii/xext.c
@@ -0,0 +1,72 @@
+/* Copyright ©2008 Kris Maglione <fbsdaemon@gmail.com>
+ * See LICENSE file for license details.
+ */
+#define _X11_VISIBLE
+#include "dat.h"
+#include "fns.h"
+
+#if RANDR_MAJOR < 1
+# error XRandR versions less than 1.0 are not supported
+#endif
+
+static void randr_screenchange(XRRScreenChangeNotifyEvent*);
+
+bool have_RandR;
+int randr_eventbase;
+
+void
+xext_init(void) {
+ randr_init();
+}
+
+void
+xext_event(XEvent *e) {
+
+ if(have_RandR && (ulong)(e->type - randr_eventbase) < RRNumberEvents) {
+ e->type -= randr_eventbase;
+ randr_event(e);
+ }
+}
+
+void
+randr_init(void) {
+ int errorbase, major, minor;
+
+ have_RandR = XRRQueryExtension(display, &randr_eventbase, &errorbase);
+ if(have_RandR)
+ if(XRRQueryVersion(display, &major, &minor) && major < 1)
+ have_RandR = false;
+ if(!have_RandR)
+ return;
+ XRRSelectInput(display, scr.root.w, RRScreenChangeNotifyMask);
+}
+
+static void
+randr_screenchange(XRRScreenChangeNotifyEvent *ev) {
+ View *v;
+ Point d;
+
+ XRRUpdateConfiguration((XEvent*)ev);
+
+ d.x = ev->width - Dx(screen->r);
+ d.y = ev->height - Dy(screen->r);
+ for(v=view; v; v=v->next) {
+ v->r.max.x += d.x;
+ v->r.max.y += d.y;
+ }
+ screen->r = Rect(0, 0, ev->width, ev->height);
+ bar_resize(screen);
+}
+
+void
+randr_event(XEvent *e) {
+
+ switch(e->type) {
+ default:
+ break;
+ case RRScreenChangeNotify: /* Yuck. */
+ randr_screenchange((XRRScreenChangeNotifyEvent*)e);
+ break;
+ }
+}
+
diff --git a/include/util.h b/include/util.h
@@ -33,10 +33,11 @@ char* estrdup(const char*);
void fatal(const char*, ...);
int max(int, int);
int min(int, int);
-char* str_nil(char*);
uint strlcat(char*, const char*, uint);
+char* sxprint(const char*, ...);
uint tokenize(char **, uint, char*, char);
int utflcpy(char*, const char*, int);
+char* vsxprint(const char*, va_list);
#define die(x) \
_die(__FILE__, __LINE__, x)
diff --git a/include/x11.h b/include/x11.h
@@ -6,21 +6,22 @@
#ifdef _X11_VISIBLE
# include <X11/Xatom.h>
# include <X11/extensions/shape.h>
+# include <X11/extensions/Xrandr.h>
#endif
#undef Window
#undef Font
#undef Screen
enum Align {
- NORTH = 0x01,
- EAST = 0x02,
- SOUTH = 0x04,
- WEST = 0x08,
- NEAST = NORTH | EAST,
- NWEST = NORTH | WEST,
- SEAST = SOUTH | EAST,
- SWEST = SOUTH | WEST,
- CENTER = NEAST | SWEST,
+ North = 0x01,
+ East = 0x02,
+ South = 0x04,
+ West = 0x08,
+ NEast = North | East,
+ NWest = North | West,
+ SEast = South | East,
+ SWest = South | West,
+ Center = NEast | SWest,
};
typedef enum Align Align;
@@ -76,13 +77,16 @@ struct Window {
};
struct WinHints {
- Point min, max;
- Point base, baspect;
- Point inc;
+ Point min;
+ Point max;
+ Point base;
+ Point baspect;
+ Point inc;
+ Point grav;
Rectangle aspect;
- Point grav;
- bool gravstatic;
- bool position;
+ XWindow group;
+ bool gravstatic;
+ bool position;
};
struct Handlers {
@@ -221,6 +225,7 @@ void warppointer(Point);
Window* window(XWindow);
long winprotocols(Window*);
Atom xatom(char*);
+void sendmessage(Window*, char*, char*, long, long, long);
XRectangle XRect(Rectangle);
Rectangle gravitate(Rectangle dst, Rectangle src, Point grav);
Rectangle insetrect(Rectangle, int);
diff --git a/libwmii_hack/hack.c b/libwmii_hack/hack.c
@@ -24,6 +24,7 @@ static long ntypes;
static char* tags[32];
static long ntags;
static long pid;
+static long stime;
static char hostname[256];
static long nmsec;
@@ -88,6 +89,10 @@ init(Display *d) { /* Hrm... assumes one display... */
ntags = n;
free(s);
}
+ if((s = getenv("WMII_HACK_TIME"))) {
+ getlong(s, &stime);
+ unsetenv("WMII_HACK_TIME");
+ }
pid = getpid();
gethostname(hostname, sizeof hostname);
@@ -95,12 +100,17 @@ init(Display *d) { /* Hrm... assumes one display... */
static void
setprops(Display *d, Window w) {
+ long *l;
if(!xlib)
init(d);
- changeprop_long(d, w, "_NET_WM_PID", "CARDINAL", &pid, 1);
- changeprop_string(d, w, "_NET_WM_CLIENT_MACHINE", hostname);
+ if(getprop_long(d, w, "_NET_WM_PID", "CARDINAL", 0L, &l, 1L))
+ free(l);
+ else {
+ changeprop_long(d, w, "_NET_WM_PID", "CARDINAL", &pid, 1);
+ changeprop_string(d, w, "WM_CLIENT_MACHINE", hostname);
+ }
/* Kludge. */
if(nmsec == 0)
@@ -114,6 +124,8 @@ setprops(Display *d, Window w) {
changeprop_long(d, w, "_NET_WM_WINDOW_TYPE", "ATOM", (long*)types, ntypes);
if(ntags)
changeprop_textlist(d, w, "_WMII_TAGS", "UTF8_STRING", tags);
+ if(stime)
+ changeprop_long(d, w, "_WMII_LAUNCH_TIME", "CARDINAL", &stime, 1);
}
int
diff --git a/libwmii_hack/x11.c b/libwmii_hack/x11.c
@@ -79,7 +79,6 @@ freestringlist(char *list[]) {
}
#endif
-#if 0
static ulong
getprop(Display *display, Window w, char *prop, char *type, Atom *actual, int *format, ulong offset, uchar **ret, ulong length) {
Atom typea;
@@ -102,7 +101,6 @@ getprop(Display *display, Window w, char *prop, char *type, Atom *actual, int *f
}
return n;
}
-#endif
#if 0
static ulong
@@ -113,7 +111,6 @@ getproperty(Display *display, Window w, char *prop, char *type, Atom *actual, ul
}
#endif
-#if 0
static ulong
getprop_long(Display *display, Window w, char *prop, char *type, ulong offset, long **ret, ulong length) {
Atom actual;
@@ -127,7 +124,6 @@ getprop_long(Display *display, Window w, char *prop, char *type, ulong offset, l
*ret = 0;
return 0;
}
-#endif
#ifdef notdef
static char**
diff --git a/libwmii_hack/x11.h b/libwmii_hack/x11.h
@@ -10,7 +10,7 @@ static void changeprop_textlist(Display*, Window, char*, char*, char*[]);
static void changeproperty(Display*, Window, char*, char*, int width, uchar*, int);
/* static void delproperty(Display*, Window, char*); */
/* static void freestringlist(char**); */
-/* static ulong getprop_long(Display*, Window, char*, char*, ulong, long**, ulong); */
+static ulong getprop_long(Display*, Window, char*, char*, ulong, long**, ulong);
/* static char* getprop_string(Display*, Window, char*); */
/* static int getprop_textlist(Display*, Window, char*, char**[]); */
/* static ulong getproperty(Display*, Window, char*, char*, Atom*, ulong, uchar**, ulong); */
diff --git a/man/wmiiloop.tex b/man/wmiiloop.tex
@@ -1,4 +1,4 @@
-\begin{Name}{1}{wmiiloop}{Kris Maglione}{}{wmiir}
+\begin{Name}{1}{wmiiloop}{Kris Maglione}{}{wmiiloop}
\Prog{wmiiloop}-VERSION
\end{Name}
diff --git a/mk/hdr.mk b/mk/hdr.mk
@@ -22,8 +22,12 @@ all:
${COMPILE} ${<:.c=.o} $<
${LINK} $@ ${<:.c=.o}
-
-.rc.O .sh.O .awk.O:
+.sh.O:
+ echo FILTER $(BASE)$<
+ $(FILTER) $< >$@
+ sh -n $@
+ chmod 0755 $@
+.rc.O .awk.O:
echo FILTER $(BASE)$<
$(FILTER) $< >$@
chmod 0755 $@
diff --git a/mk/so.mk b/mk/so.mk
@@ -1,5 +1,5 @@
SOPTARG = $(ROOT)/lib/$(TARG)
-SO = $(PTARG).so
+SO = $(SOPTARG).so
SONAME = $(TARG).so
OFILES_PIC = ${OBJ:=.o_pic}
diff --git a/rc/rc.wmii.rc b/rc/rc.wmii.rc
@@ -15,8 +15,8 @@ RIGHT=l
# Theme
wmiifont='drift,-*-fixed-*-*-*-*-9-*-*-*-*-*-*-*'
wmiifont='-*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*'
-wmiinormcol=`{echo '#222222 #5FBF77 #2A7F3F'}
-wmiifocuscol=`{echo '#ffffff #153F1F #2A7F3F'}
+wmiinormcol=`{echo '#000000 #c1c48b #81654f'}
+wmiifocuscol=`{echo '#000000 #81654f #000000'}
wmiibackground='#333333'
# Programs
@@ -24,7 +24,8 @@ WMII_TERM=(xterm)
# Column Rules
wmiir write /colrules <<!
-/./ -> 60+40
+/gimp/ -> 17+83+41
+/./ -> 62+38 # Golden Ratio
!
# Tagging Rules
@@ -32,7 +33,6 @@ wmiir write /tagrules <<!
/VLC/ -> ~
/XMMS.*/ -> ~
/MPlayer.*/ -> ~
-/.*/ -> sel
!
# Status Bar Info
@@ -101,9 +101,8 @@ fn Action {
} &
}
-# Actions
fn Action-rehash {
- comm -23 <{ls $WMII_NS_DIR/proglist.* | awk -F'\.' '{print $NF}'} \
+ comm -23 <{ls $WMII_NS_DIR/proglist.* >[2]/dev/null | awk -F'\.' '{print $NF}'} \
<{ps | awk '{print $2}'} |
while(id=`{read})
rm $WMII_NS_DIR/proglist.$id
@@ -193,7 +192,7 @@ wmiir write /ctl <<!
focuscolors $wmiifocuscol
normcolors $wmiinormcol
!
-xsetroot -solid $WMII_BACKGROUND
+xsetroot -solid $wmiibackground
# Source Overrides
Action overridekeys