Significant changes:

EWMH support
	Improvements to fullscreen mode
	Improvements in focus, especially in no-input windows
	Cleaner rc.wmii, with wmii.rc include
	Filter out gcc error/warning dups
This commit is contained in:
Kris Maglione 2008-01-14 15:42:21 -05:00
parent ad970838dc
commit aef6e4c22e
54 changed files with 2633 additions and 1927 deletions

View File

@ -23,5 +23,6 @@ deb:
dpkg-buildpackage -rfakeroot
include ${ROOT}/mk/dir.mk
include ${ROOT}/mk/common.mk
INSTDIRS = ${PDIRS}

View File

@ -27,5 +27,10 @@ OWMIIR=wmiir.o ${OFILES} ${LIBIXP}
wmiir.O: ${OWMIIR}
${LINK} $@ ${STATIC} ${OWMIIR}
OMENU=menu.o wmii/x11.o ${OFILES} ${LIBIXP}
menu.O: ${OMENU} dall
${LINK} $@ ${OMENU}
wmii9menu.O: wmii9menu.o ${OFILES}
${LINK} $@ $*.o ${OFILES} ${LIBX11}

View File

@ -1,6 +1,8 @@
/* Written by Kris Maglione <fbsdaemon at gmail dot com> */
/* Public domain */
#include <errno.h>
#include <sys/types.h>
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
@ -44,6 +46,19 @@ fatal(const char *fmt, ...) {
exit(1);
}
void
_die(char *file, int line, char *msg) {
fprint(2, "%s: dieing at %s:%d: %s\n",
file, line, msg);
kill(getpid(), SIGABRT);
abort(); /* Adds too many frames:
* _die()
* abort()
* raise(SIGABRT)
* kill(getpid(), SIGABRT)
*/
}
/* Can't malloc */
static void
mfatal(char *name, uint size) {

View File

@ -5,7 +5,7 @@ include ${ROOT}/mk/wmii.mk
main.c: ${ROOT}/mk/wmii.mk
TARG = wmii
HFILES= dat.h fns.h x11.h
HFILES= dat.h fns.h
LIB = ${LIBIXP}
LDFLAGS += -lm ${LIBX11} -lXext ${LIBICONV} -lregexp9 -lbio -lfmt -lutf
@ -15,19 +15,20 @@ OBJ = area \
client \
column \
event \
ewmh \
frame \
fs \
fs \
geom \
key \
main \
map \
key \
main \
map \
message \
mouse \
rule \
rule \
printevent\
utf \
view \
x11 \
utf \
view \
x11 \
../util
include ${ROOT}/mk/one.mk

View File

@ -5,14 +5,11 @@
#include "dat.h"
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "fns.h"
static void place_frame(Frame *f);
Client *
Client*
area_selclient(Area *a) {
if(a && a->sel)
return a->sel->client;
@ -41,8 +38,8 @@ area_name(Area *a) {
return buf;
}
Area *
create_area(View *v, Area *pos, uint w) {
Area*
area_create(View *v, Area *pos, uint w) {
static ushort id = 1;
uint areanum, i;
uint minwidth;
@ -61,7 +58,7 @@ create_area(View *v, Area *pos, uint w) {
colnum = areanum - 1;
if(w == 0) {
if(colnum >= 0) {
w = newcolw(v, i);
w = view_newcolw(v, i);
if (w == 0)
w = Dx(screen->r) / (colnum + 1);
}
@ -75,7 +72,7 @@ create_area(View *v, Area *pos, uint w) {
return nil;
if(pos)
scale_view(v, Dx(screen->r) - w);
view_scale(v, Dx(screen->r) - w);
a = emallocz(sizeof *a);
a->view = v;
@ -105,24 +102,24 @@ create_area(View *v, Area *pos, uint w) {
a->floating = True;
if(v->sel == nil)
focus_area(a);
area_focus(a);
if(!a->floating)
write_event("CreateColumn %ud\n", i);
event("CreateColumn %ud\n", i);
return a;
}
void
destroy_area(Area *a) {
area_destroy(Area *a) {
Client *c;
Area *ta;
View *v;
uint i;
int idx;
v = a->view;
if(a->frame)
fatal("destroying non-empty area");
die("destroying non-empty area");
if(v->revert == a)
v->revert = nil;
@ -131,9 +128,7 @@ destroy_area(Area *a) {
if(c->revert == a)
c->revert = nil;
i = 0;
for(ta=v->area; ta != a; ta=ta->next)
i++;
idx = area_idx(a);
if(a->prev)
ta = a->prev;
@ -149,15 +144,17 @@ destroy_area(Area *a) {
if(ta && v->sel == a) {
if(ta->floating && ta->next)
ta = ta->next;
focus_area(ta);
area_focus(ta);
}
write_event("DestroyColumn %ud\n", i);
event("DestroyArea %d\n", idx);
/* Deprecated */
event("DestroyColumn %d\n", idx);
free(a);
}
void
send_to_area(Area *to, Frame *f) {
area_moveto(Area *to, Frame *f) {
Area *from;
assert(to->view == f->view);
@ -165,18 +162,20 @@ send_to_area(Area *to, Frame *f) {
from = f->area;
if(to->floating != from->floating) {
Rectangle temp = f->revert;
Rectangle tr;
tr = f->revert;
f->revert = f->r;
f->r = temp;
f->r = tr;
}
f->client->revert = from;
detach_from_area(f);
attach_to_area(to, f);
area_detach(f);
area_attach(to, f);
}
void
attach_to_area(Area *a, Frame *f) {
area_attach(Area *a, Frame *f) {
uint n_frame;
Frame *ft;
Client *c;
@ -196,25 +195,30 @@ attach_to_area(Area *a, Frame *f) {
f->r.max.y = Dy(a->r) / n_frame;
}
insert_frame(a->sel, f);
frame_insert(a->sel, f);
if(a->floating) {
place_frame(f);
resize_client(f->client, &f->r);
client_resize(f->client, f->r);
}
focus_frame(f, False);
restack_view(a->view);
if(!a->sel) {
if(a == a->view->sel)
frame_focus(f);
else
a->sel = f;
}
view_restack(a->view);
if(!a->floating)
arrange_column(a, False);
column_arrange(a, False);
if(a->frame)
assert(a->sel);
}
void
detach_from_area(Frame *f) {
area_detach(Frame *f) {
Frame *pr;
Client *c, *cp;
Area *a;
@ -225,27 +229,27 @@ detach_from_area(Frame *f) {
c = f->client;
pr = f->aprev;
remove_frame(f);
frame_remove(f);
if(a->sel == f) {
if(!pr)
pr = a->frame;
if(pr && (v->sel == a))
focus_frame(pr, False);
frame_focus(pr);
else
a->sel = pr;
}
if(!a->floating) {
if(a->frame)
arrange_column(a, False);
column_arrange(a, False);
else {
if(v->area->next->next)
destroy_area(a);
area_destroy(a);
else if((a->frame == nil) && (v->area->frame))
focus_area(v->area);
area_focus(v->area);
arrange_view(v);
view_arrange(v);
}
}else if(!a->frame) {
if(c->trans) {
@ -253,13 +257,13 @@ detach_from_area(Frame *f) {
if(cp && cp->frame) {
a = cp->sel->area;
if(a->view == v) {
focus_area(a);
area_focus(a);
return;
}
}
}
if(v->area->next->frame)
focus_area(v->area->next);
area_focus(v->area->next);
}else
assert(a->sel);
}
@ -279,7 +283,7 @@ bit_set(uint *field, uint width, uint x, uint y, int set) {
field[y*width + bx] &= ~mask;
}
static Bool
static bool
bit_get(uint *field, uint width, uint x, uint y) {
enum { divisor = sizeof(uint) * 8 };
uint bx, mask;
@ -292,11 +296,11 @@ bit_get(uint *field, uint width, uint x, uint y) {
return (field[y*width + bx] & mask) != 0;
}
/* TODO: Replace this. */
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;
@ -306,7 +310,7 @@ place_frame(Frame *f) {
Frame *fr;
Client *c;
Area *a;
Bool fit;
bool fit;
uint i, j, x, y, cx, cy, maxx, maxy, diff, num;
int snap;
@ -321,7 +325,7 @@ place_frame(Frame *f) {
if(c->trans)
return;
if(c->fullscreen || c->w.hints->position || starting) {
f->r = gravclient(c, c->r);
f->r = client_grav(c, c->r);
return;
}
if(!field) {
@ -398,23 +402,25 @@ place_frame(Frame *f) {
p1 = subpt(p1, f->r.min);
f->r = rectaddpt(f->r, p1);
rects = rects_of_view(a->view, &num, nil);
rects = view_rects(a->view, &num, nil);
snap_rect(rects, num, &f->r, &align, snap);
if(rects)
free(rects);
}
void
focus_area(Area *a) {
area_focus(Area *a) {
Frame *f;
View *v;
Area *old_a;
int i;
v = a->view;
f = a->sel;
old_a = v->sel;
if(view_fullscreen_p(v) && a != v->area)
return;
v->sel = a;
if((old_a) && (a->floating != old_a->floating))
@ -423,18 +429,20 @@ focus_area(Area *a) {
if(v != screen->sel)
return;
move_focus(old_a->sel, f);
if(f)
focus_client(f->client);
client_focus(f->client);
else
focus_client(nil);
client_focus(nil);
if(a != old_a) {
i = 0;
for(a = v->area; a != v->sel; a = a->next)
i++;
event("AreaFocus %s\n", area_name(a));
/* Deprecated */
if(a->floating)
write_event("FocusFloating\n");
event("FocusFloating\n");
else
write_event("ColumnFocus %d\n", i);
event("ColumnFocus %d\n", area_idx(a));
}
}

View File

@ -3,15 +3,13 @@
* See LICENSE file for license details.
*/
#include "dat.h"
#include <stdio.h>
#include <string.h>
#include "fns.h"
static Handlers handlers;
static Bar *free_bars;
void
initbar(WMScreen *s) {
bar_init(WMScreen *s) {
WinAttr wa;
s->brect = s->r;
@ -35,12 +33,12 @@ initbar(WMScreen *s) {
mapwin(s->barwin);
}
Bar *
create_bar(Bar **bp, char *name) {
Bar*
bar_create(Bar **bp, const char *name) {
static uint id = 1;
Bar *b;
b = bar_of_name(*bp, name);;
b = bar_find(*bp, name);;
if(b)
return b;
@ -56,8 +54,8 @@ create_bar(Bar **bp, char *name) {
utflcpy(b->name, name, sizeof(b->name));
b->col = def.normcolor;
for(; *bp; bp = &(*bp)->next)
if(strcmp((*bp)->name, name) >= 0)
for(; *bp; bp = &bp[0]->next)
if(strcmp(bp[0]->name, name) >= 0)
break;
b->next = *bp;
*bp = b;
@ -66,10 +64,10 @@ create_bar(Bar **bp, char *name) {
}
void
destroy_bar(Bar **bp, Bar *b) {
bar_destroy(Bar **bp, Bar *b) {
Bar **p;
for(p = bp; *p; p = &(*p)->next)
for(p = bp; *p; p = &p[0]->next)
if(*p == b) break;
*p = b->next;
@ -78,7 +76,7 @@ destroy_bar(Bar **bp, Bar *b) {
}
void
resize_bar(WMScreen *s) {
bar_resize(WMScreen *s) {
View *v;
s->brect = s->r;
@ -86,14 +84,14 @@ resize_bar(WMScreen *s) {
reshapewin(s->barwin, s->brect);
XSync(display, False);
draw_bar(s);
sync();
bar_draw(s);
for(v = view; v; v = v->next)
arrange_view(v);
view_arrange(v);
}
void
draw_bar(WMScreen *s) {
bar_draw(WMScreen *s) {
Bar *b, *tb, *largest, **pb;
Rectangle r;
Align align;
@ -113,12 +111,11 @@ draw_bar(WMScreen *s) {
width += Dx(b->r);
}
if(width > Dx(s->brect)) { /* Not enough room. Shrink bars until they all fit. */
for(nb = 0; nb < nelem(s->bar); nb++)
for(b = s->bar[nb]; b; b=b->next) {
for(pb = &largest; *pb; pb = &(*pb)->smaller)
if(Dx((*pb)->r) < Dx(b->r))
for(pb = &largest; *pb; pb = &pb[0]->smaller)
if(Dx(pb[0]->r) < Dx(b->r))
break;
b->smaller = *pb;
*pb = b;
@ -131,13 +128,14 @@ draw_bar(WMScreen *s) {
if(Dx(tb->r) * shrink >= Dx(tb->smaller->r))
break;
}
SET(shrink);
if(tb)
for(b = largest; b != tb->smaller; b = b->smaller)
b->r.max.x *= shrink;
width += tw * shrink;
}
SET(tb);
tb = nil;
for(nb = 0; nb < nelem(s->bar); nb++)
for(b = s->bar[nb]; b; tb=b, b=b->next) {
if(b == s->bar[BarRight])
@ -159,11 +157,11 @@ draw_bar(WMScreen *s) {
border(screen->ibuf, b->r, 1, b->col.border);
}
copyimage(s->barwin, r, screen->ibuf, ZP);
XSync(display, False);
sync();
}
Bar*
bar_of_name(Bar *bp, const char *name) {
bar_find(Bar *bp, const char *name) {
Bar *b;
for(b = bp; b; b = b->next)
@ -180,16 +178,16 @@ bdown_event(Window *w, XButtonPressedEvent *e) {
/* Ungrab so a menu can receive events before the button is released */
XUngrabPointer(display, e->time);
XSync(display, False);
sync();
for(b=screen->bar[BarLeft]; b; b=b->next)
if(ptinrect(Pt(e->x, e->y), b->r)) {
write_event("LeftBarMouseDown %d %s\n", e->button, b->name);
if(rect_haspoint_p(Pt(e->x, e->y), b->r)) {
event("LeftBarMouseDown %d %s\n", e->button, b->name);
return;
}
for(b=screen->bar[BarRight]; b; b=b->next)
if(ptinrect(Pt(e->x, e->y), b->r)) {
write_event("RightBarMouseDown %d %s\n", e->button, b->name);
if(rect_haspoint_p(Pt(e->x, e->y), b->r)) {
event("RightBarMouseDown %d %s\n", e->button, b->name);
return;
}
}
@ -198,26 +196,24 @@ static void
bup_event(Window *w, XButtonPressedEvent *e) {
Bar *b;
USED(w);
USED(e);
USED(w, e);
for(b=screen->bar[BarLeft]; b; b=b->next)
if(ptinrect(Pt(e->x, e->y), b->r)) {
write_event("LeftBarClick %d %s\n", e->button, b->name);
if(rect_haspoint_p(Pt(e->x, e->y), b->r)) {
event("LeftBarClick %d %s\n", e->button, b->name);
return;
}
for(b=screen->bar[BarRight]; b; b=b->next)
if(ptinrect(Pt(e->x, e->y), b->r)) {
write_event("RightBarClick %d %s\n", e->button, b->name);
if(rect_haspoint_p(Pt(e->x, e->y), b->r)) {
event("RightBarClick %d %s\n", e->button, b->name);
return;
}
}
static void
expose_event(Window *w, XExposeEvent *e) {
USED(w);
USED(e);
draw_bar(screen);
USED(w, e);
bar_draw(screen);
}
static Handlers handlers = {

View File

@ -4,9 +4,6 @@
*/
#include "dat.h"
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xatom.h>
#include "fns.h"
@ -25,8 +22,8 @@ enum {
| ButtonReleaseMask
};
Client *
create_client(XWindow w, XWindowAttributes *wa) {
Client*
client_create(XWindow w, XWindowAttributes *wa) {
Client **t, *c;
WinAttr fwa;
@ -40,13 +37,13 @@ create_client(XWindow w, XWindowAttributes *wa) {
c->w.w = w;
c->w.r = c->r;
prop_client(c, xatom("WM_PROTOCOLS"));
prop_client(c, xatom("WM_TRANSIENT_FOR"));
prop_client(c, xatom("WM_NORMAL_HINTS"));
prop_client(c, xatom("WM_HINTS"));
prop_client(c, xatom("WM_CLASS"));
prop_client(c, xatom("WM_NAME"));
prop_client(c, xatom("_MOTIF_WM_HINTS"));
client_prop(c, xatom("WM_PROTOCOLS"));
client_prop(c, xatom("WM_TRANSIENT_FOR"));
client_prop(c, xatom("WM_NORMAL_HINTS"));
client_prop(c, xatom("WM_HINTS"));
client_prop(c, xatom("WM_CLASS"));
client_prop(c, xatom("WM_NAME"));
client_prop(c, xatom("_MOTIF_WM_HINTS"));
XSetWindowBorderWidth(display, w, 0);
XAddToSaveSet(display, w);
@ -71,22 +68,24 @@ create_client(XWindow w, XWindowAttributes *wa) {
sethandler(c->framewin, &framehandler);
sethandler(&c->w, &handlers);
ewmh_initclient(c);
grab_button(c->framewin->w, AnyButton, AnyModifier);
for(t=&client ;; t=&(*t)->next)
for(t=&client ;; t=&t[0]->next)
if(!*t) {
c->next = *t;
*t = c;
break;
}
write_event("CreateClient %C\n", c);
manage_client(c);
event("CreateClient %C\n", c);
client_manage(c);
return c;
}
void
manage_client(Client *c) {
client_manage(Client *c) {
Point p;
Client *trans;
char *tags;
@ -113,39 +112,39 @@ manage_client(Client *c) {
apply_rules(c);
if(!starting)
update_views();
view_update_all();
if(c->sel->view == screen->sel)
focus(c, True);
if(!(c->w.ewmh.type & TypeSplash))
focus(c, false);
flushevents(EnterWindowMask, False);
}
static int /* Temporary Xlib error handler */
ignoreerrors(Display *d, XErrorEvent *e) {
USED(d);
USED(e);
USED(d, e);
return 0;
}
void
destroy_client(Client *c) {
client_destroy(Client *c) {
int (*handler)(Display*, XErrorEvent*);
Rectangle r;
char *dummy;
Client **tc;
Bool hide;
bool hide;
Dprint("client.c:destroy_client(%p) %s\n", c, c->name);
Dprint(DGeneric, "client.c:client_destroy(%p) %s\n", c, c->name);
unmapwin(c->framewin);
for(tc=&client; *tc; tc=&(*tc)->next)
for(tc=&client; *tc; tc=&tc[0]->next)
if(*tc == c) {
*tc = c->next;
break;
}
r = gravclient(c, ZR);
r = client_grav(c, ZR);
hide = False;
if(!c->sel || c->sel->view != screen->sel)
@ -157,8 +156,8 @@ destroy_client(Client *c) {
handler = XSetErrorHandler(ignoreerrors);
dummy = nil;
update_client_views(c, &dummy);
unmap_client(c, IconicState);
view_setclient(c, &dummy);
client_unmap(c, IconicState);
sethandler(&c->w, nil);
if(hide)
@ -167,11 +166,12 @@ destroy_client(Client *c) {
reparentwindow(&c->w, &scr.root, r.min);
destroywindow(c->framewin);
XSync(display, False);
sync();
XSetErrorHandler(handler);
XUngrabServer(display);
write_event("DestroyClient %C\n", c);
ewmh_destroyclient(c);
event("DestroyClient %C\n", c);
flushevents(EnterWindowMask, False);
free(c->w.hints);
@ -179,14 +179,24 @@ destroy_client(Client *c) {
}
/* Convenience functions */
Client *
Frame*
client_viewframe(Client *c, View *v) {
Frame *f;
for(f=c->frame; f; f=f->cnext)
if(f->area->view == v)
break;
return f;
}
Client*
selclient(void) {
if(screen->sel->sel->sel)
return screen->sel->sel->sel->client;
return nil;
}
Client *
Client*
win2client(XWindow w) {
Client *c;
for(c=client; c; c=c->next)
@ -204,7 +214,7 @@ Cfmt(Fmt *f) {
return fmtprint(f, "<nil>");
}
char *
char*
clientname(Client *c) {
if(c)
return c->name;
@ -212,7 +222,7 @@ clientname(Client *c) {
}
Rectangle
gravclient(Client *c, Rectangle rd) {
client_grav(Client *c, Rectangle rd) {
Rectangle r;
Point sp;
WinHints *h;
@ -227,17 +237,17 @@ gravclient(Client *c, Rectangle rd) {
else
r = c->sel->revert;
}else
r = client2frame(nil, c->r);
r = frame_client2rect(nil, c->r);
r = gravitate(r, c->r, h->grav);
if(h->gravstatic)
r = rectaddpt(r, sp);
return frame2client(nil, r);
return frame_rect2client(nil, r);
}else {
r = client2frame(nil, rd);
r = frame_client2rect(nil, rd);
r = gravitate(rd, r, h->grav);
if(h->gravstatic)
r = rectsubpt(r, sp);
return client2frame(nil, r);
return frame_client2rect(nil, r);
}
}
@ -252,9 +262,9 @@ frame_hints(Frame *f, Rectangle r, Align sticky) {
return r;
or = r;
r = frame2client(f, r);
r = frame_rect2client(f, r);
r = sizehint(c->w.hints, r);
r = client2frame(f, r);
r = frame_client2rect(f, r);
if(!f->area->floating) {
/* Not allowed to grow */
@ -274,25 +284,25 @@ frame_hints(Frame *f, Rectangle r, Align sticky) {
}
static void
set_client_state(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));
}
void
map_client(Client *c) {
client_map(Client *c) {
if(!c->w.mapped) {
mapwin(&c->w);
set_client_state(c, NormalState);
client_setstate(c, NormalState);
}
}
void
unmap_client(Client *c, int state) {
client_unmap(Client *c, int state) {
if(c->w.mapped) {
unmapwin(&c->w);
set_client_state(c, state);
client_setstate(c, state);
}
}
@ -307,50 +317,55 @@ unmap_frame(Client *c) {
}
void
focus(Client *c, Bool restack) {
focus(Client *c, bool user) {
View *v;
Frame *f;
f = c->sel;
if(!f)
return;
if(!user && c->noinput)
return;
v = f->area->view;
v = f->view;
if(v != screen->sel)
focus_view(screen, v);
focus_frame(c->sel, restack);
view_focus(screen, v);
frame_focus(c->sel);
}
void
focus_client(Client *c) {
client_focus(Client *c) {
flushevents(FocusChangeMask, True);
Dprint("focus_client(%p[%C]) => %s\n", c, c, clientname(c));
Dprint(DFocus, "client_focus(%p[%C]) => %s\n", c, c, clientname(c));
if((c == nil || !c->noinput) && screen->focus != c) {
Dprint("\t%s => %s\n", clientname(screen->focus), clientname(c));
if(c && c->noinput)
return;
if(screen->focus != c) {
Dprint(DFocus, "\t%s => %s\n", clientname(screen->focus), clientname(c));
if(c)
setfocus(&c->w, RevertToParent);
else
setfocus(screen->barwin, RevertToParent);
write_event("ClientFocus %C\n", c);
event("ClientFocus %C\n", c);
XSync(display, False);
sync();
flushevents(FocusChangeMask, True);
}
}
void
resize_client(Client *c, Rectangle *r) {
client_resize(Client *c, Rectangle r) {
Frame *f;
f = c->sel;
resize_frame(f, *r);
frame_resize(f, r);
if(f->area->view != screen->sel) {
unmap_client(c, IconicState);
client_unmap(c, IconicState);
unmap_frame(c);
return;
}
@ -359,24 +374,25 @@ resize_client(Client *c, Rectangle *r) {
if((f->area->mode == Colmax) && (f->area->sel != f)) {
unmap_frame(c);
unmap_client(c, IconicState);
client_unmap(c, IconicState);
}else if(f->collapsed) {
reshapewin(c->framewin, f->r);
map_frame(c);
unmap_client(c, IconicState);
client_unmap(c, IconicState);
}else {
map_client(c);
client_map(c);
reshapewin(c->framewin, f->r);
reshapewin(&c->w, f->crect);
map_frame(c);
configure_client(c);
client_configure(c);
ewmh_framesize(c);
}
flushevents(FocusChangeMask|ExposureMask, True);
}
void
set_cursor(Client *c, Cursor cur) {
client_setcursor(Client *c, Cursor cur) {
WinAttr wa;
if(c->cursor != cur) {
@ -387,7 +403,7 @@ set_cursor(Client *c, Cursor cur) {
}
void
configure_client(Client *c) {
client_configure(Client *c) {
XConfigureEvent e;
Rectangle r;
@ -405,30 +421,27 @@ configure_client(Client *c) {
e.height = Dy(r);
e.border_width = c->border;
XSendEvent(display, c->w.w,
/*propegate*/ False,
StructureNotifyMask,
(XEvent*)&e);
sendevent(&c->w, false, StructureNotifyMask, (XEvent*)&e);
}
static void
send_client_message(Client *c, char *name, char *value) {
XEvent e;
client_sendmessage(Client *c, char *name, char *value) {
XClientMessageEvent e;
e.type = ClientMessage;
e.xclient.window = c->w.w;
e.xclient.message_type = xatom(name);
e.xclient.format = 32;
e.xclient.data.l[0] = xatom(value);
e.xclient.data.l[1] = CurrentTime;
XSendEvent(display, c->w.w, False, NoEventMask, &e);
XSync(display, False);
e.window = c->w.w;
e.message_type = xatom(name);
e.format = 32;
e.data.l[0] = xatom(value);
e.data.l[1] = CurrentTime;
sendevent(&c->w, false, NoEventMask, (XEvent*)&e);
sync();
}
void
kill_client(Client * c) {
client_kill(Client * c) {
if(c->proto & WM_PROTOCOL_DELWIN)
send_client_message(c, "WM_PROTOCOLS", "WM_DELETE_WINDOW");
client_sendmessage(c, "WM_PROTOCOLS", "WM_DELETE_WINDOW");
else
XKillClient(display, c->w.w);
}
@ -442,8 +455,9 @@ fullscreen(Client *c, int fullscreen) {
if(fullscreen == c->fullscreen)
return;
write_event("Fullscreen %C %s\n", c, (fullscreen ? "on" : "off"));
event("Fullscreen %C %s\n", c, (fullscreen ? "on" : "off"));
c->fullscreen = fullscreen;
ewmh_updatestate(c);
if((f = c->sel)) {
if(fullscreen) {
@ -451,18 +465,18 @@ fullscreen(Client *c, int fullscreen) {
f->revert = f->r;
else {
f->r = f->revert;
send_to_area(f->view->area, f);
area_moveto(f->view->area, f);
}
focus_client(c);
focus(c, true);
}else
resize_frame(f, f->revert);
frame_resize(f, f->revert);
if(f->view == screen->sel)
focus_view(screen, f->view);
view_focus(screen, f->view);
}
}
void
set_urgent(Client *c, int urgent, Bool write) {
client_seturgent(Client *c, int urgent, bool write) {
XWMHints *wmh;
char *cwrite, *cnot;
Frame *f, *ff;
@ -475,11 +489,12 @@ set_urgent(Client *c, int urgent, Bool write) {
cnot = (urgent ? "" : "Not");
if(urgent != c->urgent) {
write_event("%sUrgent %C %s\n", cnot, c, cwrite);
event("%sUrgent %C %s\n", cnot, c, cwrite);
c->urgent = urgent;
ewmh_updatestate(c);
if(c->sel) {
if(c->sel->view == screen->sel)
draw_frame(c->sel);
frame_draw(c->sel);
for(f=c->frame; f; f=f->cnext) {
SET(ff);
if(!urgent)
@ -487,7 +502,7 @@ set_urgent(Client *c, int urgent, Bool write) {
for(ff=a->frame; ff; ff=ff->anext)
if(ff->client->urgent) break;
if(urgent || ff == nil)
write_event("%sUrgentTag %s %s\n", cnot, cwrite, f->view->name);
event("%sUrgentTag %s %s\n", cnot, cwrite, f->view->name);
}
}
}
@ -521,7 +536,7 @@ update_class(Client *c) {
}
static void
update_client_name(Client *c) {
client_updatename(Client *c) {
char *str;
c->name[0] = '\0';
@ -535,7 +550,7 @@ update_client_name(Client *c) {
update_class(c);
if(c->sel)
draw_frame(c->sel);
frame_draw(c->sel);
}
static void
@ -543,10 +558,10 @@ updatemwm(Client *c) {
enum {
All = 0x1,
Border = 0x2,
Title = 0x8,
FlagDecor = 0x2,
Flags = 0,
Decor = 2,
Title = 0x8,
FlagDecor = 0x2,
Flags = 0,
Decor = 2,
};
Rectangle r;
ulong *ret;
@ -557,28 +572,27 @@ updatemwm(Client *c) {
0L, (void*)&ret, 3L);
if(c->sel)
r = frame2client(c->sel, c->sel->r);
r = frame_rect2client(c->sel, c->sel->r);
c->borderless = 0;
c->titleless = 0;
if(n >= 3 && (ret[Flags]&FlagDecor)) {
if(ret[Decor]&All)
ret[Decor] ^= ~0;
c->borderless = ((ret[Decor]&Border)==0);
c->titleless = ((ret[Decor]&Title)==0);
}else {
c->borderless = 0;
c->titleless = 0;
c->borderless = !(ret[Decor]&Border);
c->titleless = !(ret[Decor]&Title);
}
free(ret);
if(c->sel) {
r = client2frame(c->sel, r);
resize_client(c, &r);
draw_frame(c->sel);
r = frame_client2rect(c->sel, r);
client_resize(c, r);
frame_draw(c->sel);
}
}
void
prop_client(Client *c, Atom a) {
client_prop(Client *c, Atom a) {
XWMHints *wmh;
char **class;
int n;
@ -593,6 +607,9 @@ prop_client(Client *c, Atom a) {
updatemwm(c);
}
else switch (a) {
default:
ewmh_prop(c, a);
break;
case XA_WM_TRANSIENT_FOR:
XGetTransientForHint(display, c->w.w, &c->trans);
break;
@ -605,7 +622,7 @@ prop_client(Client *c, Atom a) {
wmh = XGetWMHints(display, c->w.w);
if(wmh) {
c->noinput = !((wmh->flags&InputFocus) && wmh->input);
set_urgent(c, (wmh->flags & XUrgencyHint) != 0, False);
client_seturgent(c, (wmh->flags & XUrgencyHint) != 0, False);
XFree(wmh);
}
break;
@ -619,7 +636,7 @@ prop_client(Client *c, Atom a) {
break;
case XA_WM_NAME:
wmname:
update_client_name(c);
client_updatename(c);
break;
}
}
@ -632,43 +649,41 @@ configreq_event(Window *w, XConfigureRequestEvent *e) {
c = w->aux;
r = gravclient(c, ZR);
r = client_grav(c, ZR);
r.max = subpt(r.max, r.min);
if(e->value_mask&CWX)
if(e->value_mask & CWX)
r.min.x = e->x;
if(e->value_mask&CWY)
if(e->value_mask & CWY)
r.min.y = e->y;
if(e->value_mask&CWWidth)
if(e->value_mask & CWWidth)
r.max.x = e->width;
if(e->value_mask&CWHeight)
if(e->value_mask & CWHeight)
r.max.y = e->height;
if(e->value_mask&CWBorderWidth)
if(e->value_mask & CWBorderWidth)
c->border = e->border_width;
r.max = addpt(r.min, r.max);
cr = r;
r = gravclient(c, 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)
resize_client(c, &r);
client_resize(c, r);
else {
c->sel->revert = r;
configure_client(c);
client_configure(c);
}
}
static void
destroy_event(Window *w, XDestroyWindowEvent *e) {
USED(w);
USED(e);
USED(w, e);
Dprint("client.c:destroy_event(%W)\n", w);
destroy_client(w->aux);
client_destroy(w->aux);
}
static void
@ -678,11 +693,11 @@ enter_event(Window *w, XCrossingEvent *e) {
c = w->aux;
if(e->detail != NotifyInferior) {
if(screen->focus != c) {
Dprint("enter_notify(c) => %s\n", c->name);
focus(c, False);
Dprint(DGeneric, "enter_notify(c) => %s\n", c->name);
focus(c, false);
}
set_cursor(c, cursor[CurNormal]);
}else Dprint("enter_notify(c[NotifyInferior]) => %s\n", c->name);
client_setcursor(c, cursor[CurNormal]);
}else Dprint(DGeneric, "enter_notify(c[NotifyInferior]) => %s\n", c->name);
}
static void
@ -700,7 +715,7 @@ focusin_event(Window *w, XFocusChangeEvent *e) {
screen->focus = c;
if(c != old) {
if(c->sel)
draw_frame(c->sel);
frame_draw(c->sel);
}
}
@ -716,7 +731,7 @@ focusout_event(Window *w, XFocusChangeEvent *e) {
print_focus(&c_magic, "<magic>");
screen->focus = &c_magic;
if(c->sel)
draw_frame(c->sel);
frame_draw(c->sel);
}
}
@ -727,7 +742,7 @@ unmap_event(Window *w, XUnmapEvent *e) {
c = w->aux;
if(!e->send_event)
c->unmapped--;
destroy_client(c);
client_destroy(c);
}
static void
@ -738,7 +753,7 @@ map_event(Window *w, XMapEvent *e) {
c = w->aux;
if(c == selclient())
focus_client(c);
client_focus(c);
}
static void
@ -749,7 +764,7 @@ property_event(Window *w, XPropertyEvent *e) {
return;
c = w->aux;
prop_client(c, e->atom);
client_prop(c, e->atom);
}
static Handlers handlers = {
@ -783,12 +798,12 @@ newcol_client(Client *c, char *arg) {
if(!strncmp(arg, "prev", 5)) {
for(to=v->area; to; to=to->next)
if(to->next == a) break;
to = new_column(v, to, 0);
send_to_area(to, f);
to = column_new(v, to, 0);
area_moveto(to, f);
}
else if(!strncmp(arg, "next", 5)) {
to = new_column(v, a, 0);
send_to_area(to, f);
to = column_new(v, a, 0);
area_moveto(to, f);
}
else
return;
@ -797,7 +812,7 @@ newcol_client(Client *c, char *arg) {
#endif
void
update_client_views(Client *c, char **tags) {
view_setclient(Client *c, char **tags) {
Frame **fp, *f;
int cmp;
@ -806,13 +821,13 @@ update_client_views(Client *c, char **tags) {
SET(cmp);
while(*fp) {
if(*tags) {
cmp = strcmp((*fp)->view->name, *tags);
cmp = strcmp(fp[0]->view->name, *tags);
if(cmp >= 0)
break;
}
f = *fp;
detach_from_area(f);
area_detach(f);
*fp = f->cnext;
if(c->sel == f)
c->sel = *fp;
@ -820,18 +835,18 @@ update_client_views(Client *c, char **tags) {
}
if(*tags) {
if(!*fp || cmp > 0) {
f = create_frame(c, get_view(*tags));
f = frame_create(c, view_create(*tags));
if(f->view == screen->sel || !c->sel)
c->sel = f;
attach_to_view(f->view, f);
view_attach(f->view, f);
f->cnext = *fp;
*fp = f;
}
if(*fp) fp=&(*fp)->cnext;
if(fp[0]) fp=&fp[0]->cnext;
tags++;
}
}
update_views();
view_update_all();
}
static int
@ -840,8 +855,12 @@ bsstrcmp(const void *a, const void *b) {
}
static int
strpcmp(const void *a, const void *b) {
return strcmp(*(char **)a, *(char **)b);
strpcmp(const void *ap, const void *bp) {
char **a, **b;
a = (char**)ap;
b = (char**)bp;
return strcmp(*a, *b);
}
static char *badtags[] = {
@ -853,7 +872,7 @@ static char *badtags[] = {
void
apply_tags(Client *c, const char *tags) {
uint i, j, k, n;
Bool add;
bool add;
char buf[512], last;
char *toks[32], *cur;
@ -934,9 +953,9 @@ apply_tags(Client *c, const char *tags) {
}
toks[n] = nil;
update_client_views(c, toks);
view_setclient(c, toks);
changeprop_char(&c->w, "_WMII_TAGS", "UTF8_STRING", c->tags, strlen(c->tags));
changeprop_string(&c->w, "_WMII_TAGS", c->tags);
}
void

View File

@ -5,8 +5,6 @@
#include "dat.h"
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include "fns.h"
@ -76,7 +74,7 @@ unmapdiv(Divide *d) {
}
void
setdiv(Divide *d, int x) {
div_set(Divide *d, int x) {
Rectangle r;
d->x = x;
@ -140,7 +138,7 @@ update_imgs(void) {
}
void
update_divs(void) {
div_update_all(void) {
Divide **dp, *d;
Area *a;
View *v;
@ -152,12 +150,12 @@ update_divs(void) {
for(a = v->area->next; a; a = a->next) {
d = getdiv(dp);
dp = &d->next;
setdiv(d, a->r.min.x);
div_set(d, a->r.min.x);
if(!a->next) {
d = getdiv(dp);
dp = &d->next;
setdiv(d, a->r.max.x);
div_set(d, a->r.max.x);
}
}
for(d = *dp; d; d = d->next)
@ -190,17 +188,17 @@ static Handlers divhandler = {
.expose = expose_event,
};
Area *
new_column(View *v, Area *pos, uint w) {
Area*
column_new(View *v, Area *pos, uint w) {
Area *a;
a = create_area(v, pos, w);
a = area_create(v, pos, w);
if(!a)
return nil;
arrange_view(v);
view_arrange(v);
if(v == screen->sel)
focus_view(screen, v);
view_focus(screen, v);
return a;
}
@ -223,7 +221,7 @@ scale_column(Area *a) {
nuncol = 0;
dy = 0;
for(f=a->frame; f; f=f->anext) {
resize_frame(f, f->r);
frame_resize(f, f->r);
if(f->collapsed)
ncol++;
else
@ -260,7 +258,7 @@ scale_column(Area *a) {
if(f->collapsed) {
if(i < 0 && (f != a->sel)) {
f->collapsed = False;
send_to_area(f->view->area, f);
area_moveto(f->view->area, f);
continue;
}
i--;
@ -298,7 +296,7 @@ scale_column(Area *a) {
for(f=a->frame; f; f=f->anext) {
if(!f->collapsed)
f->r.max.y += f->ratio * surplus;
resize_frame(f, f->r);
frame_resize(f, f->r);
dy += Dy(f->r);
}
surplus = Dy(a->r) - dy;
@ -307,7 +305,7 @@ scale_column(Area *a) {
if(!f->collapsed) {
dy = Dy(f->r);
f->r.max.y += surplus;
resize_frame(f, f->r);
frame_resize(f, f->r);
f->r.max.y = Dy(f->crect) + labelh(def.font) + 1;
surplus -= Dy(f->r) - dy;
}
@ -329,7 +327,7 @@ scale_column(Area *a) {
}
void
arrange_column(Area *a, Bool dirty) {
column_arrange(Area *a, bool dirty) {
Frame *f;
if(a->floating || !a->frame)
@ -352,26 +350,26 @@ arrange_column(Area *a, Bool dirty) {
}
goto resize;
default:
assert(!"Can't happen");
die("can't get here");
break;
}
scale_column(a);
resize:
if(a->view == screen->sel) {
restack_view(a->view);
resize_client(a->sel->client, &a->sel->r);
view_restack(a->view);
client_resize(a->sel->client, a->sel->r);
for(f=a->frame; f; f=f->anext)
if(!f->collapsed && f != a->sel)
resize_client(f->client, &f->r);
client_resize(f->client, f->r);
for(f=a->frame; f; f=f->anext)
if(f->collapsed && f != a->sel)
resize_client(f->client, &f->r);
client_resize(f->client, f->r);
}
}
void
resize_column(Area *a, int w) {
column_resize(Area *a, int w) {
Area *an;
int dw;
@ -382,8 +380,8 @@ resize_column(Area *a, int w) {
a->r.max.x += dw;
an->r.min.x += dw;
arrange_view(a->view);
focus_view(screen, a->view);
view_arrange(a->view);
view_focus(screen, a->view);
}
static void
@ -410,18 +408,18 @@ resize_colframeh(Frame *f, Rectangle *r) {
if(fp) {
fp->r.max.y = r->min.y;
resize_frame(fp, fp->r);
frame_resize(fp, fp->r);
}
if(fn) {
fn->r.min.y = r->max.y;
resize_frame(fn, fn->r);
frame_resize(fn, fn->r);
}
resize_frame(f, *r);
frame_resize(f, *r);
}
void
resize_colframe(Frame *f, Rectangle *r) {
column_resizeframe(Frame *f, Rectangle *r) {
Area *a, *al, *ar;
View *v;
uint minw;
@ -441,29 +439,26 @@ resize_colframe(Frame *f, Rectangle *r) {
else
r->min.x = max(r->min.x, 0);
if(ar) {
if(maxx >= ar->r.max.x - minw)
maxx = ar->r.max.x - minw;
}
if(ar)
maxx = min(maxx, a->r.max.x - minw);
else
if(maxx > screen->r.max.x)
maxx = screen->r.max.x;
maxx = min(maxx, screen->r.max.x);
dx = a->r.min.x - r->min.x;
dw = maxx - a->r.max.x;
if(al) {
al->r.max.x -= dx;
arrange_column(al, False);
column_arrange(al, False);
}
if(ar) {
ar->r.max.x -= dw;
arrange_column(ar, False);
column_arrange(ar, False);
}
resize_colframeh(f, r);
a->r.max.x = maxx;
arrange_view(a->view);
view_arrange(a->view);
focus_view(screen, v);
view_focus(screen, v);
}

View File

@ -6,43 +6,40 @@
#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"
#define NORMCOLORS "#222222 #eeeeee #666666"
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,
};
typedef struct CTuple CTuple;
typedef enum Align Align;
struct CTuple {
ulong bg;
ulong fg;
ulong border;
char colstr[24]; /* #RRGGBB #RRGGBB #RRGGBB */
enum EWMHType {
TypeDesktop = 1<<0,
TypeDock = 1<<1,
TypeToolbar = 1<<2,
TypeMenu = 1<<3,
TypeUtility = 1<<4,
TypeSplash = 1<<5,
TypeDialog = 1<<6,
TypeNormal = 1<<7,
};
enum {
Coldefault, Colstack, Colmax,
};
#define TOGGLE(x) \
(x == On ? "On" : \
x == Off ? "Off" : \
x == Toggle ? "Toggle" : \
"<toggle>")
enum {
Off,
On,
@ -62,202 +59,222 @@ enum {
WM_PROTOCOL_DELWIN = 1,
};
enum DebugOpt {
DEvent = 1<<0,
DEwmh = 1<<1,
DFocus = 1<<2,
DGeneric= 1<<3,
};
/* Data Structures */
typedef struct View View;
typedef struct Area Area;
typedef struct Frame Frame;
typedef struct Bar Bar;
typedef struct Client Client;
typedef struct Divide Divide;
typedef struct Frame Frame;
typedef struct Key Key;
typedef struct Bar Bar;
typedef struct Rule Rule;
typedef struct Ruleset Ruleset;
typedef struct WMScreen WMScreen;
typedef struct Map Map;
typedef struct MapEnt MapEnt;
typedef struct Rule Rule;
typedef struct Ruleset Ruleset;
typedef struct View View;
typedef struct WMScreen WMScreen;
struct Map {
MapEnt **bucket;
uint nhash;
MapEnt**bucket;
uint nhash;
};
struct MapEnt {
ulong hash;
char *key;
void *val;
MapEnt *next;
ulong hash;
const char* key;
void* val;
MapEnt* next;
};
struct View {
View *next;
char name[256];
ushort id;
Area *area;
Area *sel;
Area *revert;
View* next;
char name[256];
ushort id;
Area* area;
Area* sel;
Area* revert;
};
struct Area {
Area *next, *prev;
Frame *frame;
Frame *stack;
Frame *sel;
View *view;
Bool floating;
ushort id;
int mode;
Rectangle r;
Area* next;
Area* prev;
Frame* frame;
Frame* stack;
Frame* sel;
View* view;
bool floating;
ushort id;
int mode;
Rectangle r;
};
struct Frame {
Frame *cnext;
Frame *anext, *aprev;
Frame *snext, *sprev;
View *view;
Area *area;
ushort id;
Rectangle r;
Rectangle crect;
Rectangle revert;
Client *client;
Bool collapsed;
Rectangle grabbox;
Rectangle titlebar;
float ratio;
Frame* cnext;
Frame* anext;
Frame* aprev;
Frame* snext;
Frame* sprev;
View* view;
Area* area;
Client* client;
ushort id;
bool collapsed;
float ratio;
Rectangle r;
Rectangle crect;
Rectangle revert;
Rectangle grabbox;
Rectangle titlebar;
};
struct Client {
Client *next;
Area *revert;
Frame *frame;
Frame *sel;
char name[256];
char tags[256];
char props[512];
uint border;
int proto;
Bool floating;
Bool fixedsize;
Bool fullscreen;
Bool urgent;
Bool borderless;
Bool titleless;
Bool noinput;
int unmapped;
Window w;
XWindow trans;
Window *framewin;
Cursor cursor;
Client* next;
Area* revert;
Frame* frame;
Frame* sel;
Window w;
Window* framewin;
XWindow trans;
Cursor cursor;
Rectangle r;
XSizeHints size;
GC gc;
char name[256];
char tags[256];
char props[512];
uint border;
int proto;
char floating;
char fixedsize;
char fullscreen;
char urgent;
char borderless;
char titleless;
char noinput;
int unmapped;
};
struct Divide {
Divide *next;
Window *w;
Bool mapped;
int x;
Divide* next;
Window* w;
bool mapped;
int x;
};
struct Key {
Key *next;
Key *lnext;
Key *tnext;
ushort id;
char name[128];
ulong mod;
KeyCode key;
Key* next;
Key* lnext;
Key* tnext;
ushort id;
char name[128];
ulong mod;
KeyCode key;
};
struct Bar {
Bar *next;
Bar *smaller;
char buf[280];
char text[256];
char name[256];
ushort id;
Bar* next;
Bar* smaller;
char buf[280];
char text[256];
char name[256];
ushort id;
Rectangle r;
CTuple col;
CTuple col;
};
struct Rule {
Rule *next;
Reprog *regex;
char value[256];
Rule* next;
Reprog* regex;
char value[256];
};
struct Ruleset {
Rule *rule;
char *string;
uint size;
Rule *rule;
char *string;
uint size;
};
#ifndef EXTERN
# define EXTERN extern
#endif
/* global variables */
struct {
CTuple focuscolor;
CTuple normcolor;
Font *font;
uint border;
uint snap;
char *keys;
uint keyssz;
EXTERN struct {
CTuple focuscolor;
CTuple normcolor;
Font* font;
char* keys;
uint keyssz;
Ruleset tagrules;
Ruleset colrules;
char grabmod[5];
ulong mod;
int colmode;
char grabmod[5];
ulong mod;
uint border;
uint snap;
int colmode;
} def;
enum {
BarLeft, BarRight
};
struct WMScreen {
Bar *bar[2];
View *sel;
Client *focus;
Client *hasgrab;
Window *barwin;
Image *ibuf;
#define BLOCK(x) do { x; }while(0)
EXTERN struct WMScreen {
Bar* bar[2];
View* sel;
Client* focus;
Client* hasgrab;
Window* barwin;
Image* ibuf;
Rectangle r;
Rectangle brect;
} *screens, *screen;
Client *client;
View *view;
Key *key;
Divide *divs;
Client c_magic;
Client c_root;
EXTERN Client* client;
EXTERN View* view;
EXTERN Key* key;
EXTERN Divide* divs;
EXTERN Client c_magic;
EXTERN Client c_root;
Handlers framehandler;
EXTERN Handlers framehandler;
char buffer[8092];
EXTERN char buffer[8092];
EXTERN char* _buffer;
static char* const _buf_end = buffer + sizeof buffer;
#define bufclear() \
BLOCK( _buffer = buffer; _buffer[0] = '\0' )
#define bufprint(...) \
_buffer = seprint(_buffer, _buf_end, __VA_ARGS__)
/* IXP */
IxpServer srv;
Ixp9Srv p9srv;
EXTERN IxpServer srv;
EXTERN Ixp9Srv p9srv;
/* X11 */
uint num_screens;
uint valid_mask;
uint num_lock_mask;
Bool sel_screen;
EXTERN uint num_screens;
EXTERN uint valid_mask;
EXTERN uint numlock_mask;
EXTERN bool sel_screen;
Image xor;
EXTERN Cursor cursor[CurLast];
Cursor cursor[CurLast];
void (*handler[LASTEvent]) (XEvent *);
typedef void (*XHandler)(XEvent*);
EXTERN XHandler handler[LASTEvent];
/* Misc */
Image *broken;
Bool starting;
Bool verbose;
char *user;
char *execstr;
EXTERN bool starting;
EXTERN char* user;
EXTERN char* execstr;
EXTERN int debug;
#define Debug if(verbose)
#define Dprint(...) do{ Debug fprint(2, __VA_ARGS__); }while(0)
#define Debug(x) if(debug&(x))
#define Dprint(x, ...) BLOCK( Debug(x) fprint(2, __VA_ARGS__) )

View File

@ -2,14 +2,14 @@
* See LICENSE file for license details.
*/
#include "dat.h"
#include <stdio.h>
#include <X11/keysym.h>
#include "fns.h"
#include "printevent.h"
void
dispatch_event(XEvent *e) {
Debug printevent(e);
Debug(DEvent)
printevent(e);
if(handler[e->type])
handler[e->type](e);
}
@ -17,7 +17,7 @@ dispatch_event(XEvent *e) {
#define handle(w, fn, ev) if(!(w)->handler->fn) {}else (w)->handler->fn((w), ev)
uint
flushevents(long event_mask, Bool dispatch) {
flushevents(long event_mask, bool dispatch) {
XEvent ev;
uint n = 0;
@ -72,6 +72,14 @@ configurerequest(XEvent *e) {
}
}
static void
clientmessage(XEvent *e) {
XClientMessageEvent *ev;
ev = &e->xclient;
ewmh_clientmessage(ev);
}
static void
destroynotify(XEvent *e) {
XDestroyWindowEvent *ev;
@ -82,7 +90,7 @@ destroynotify(XEvent *e) {
if((w = findwin(ev->window)))
handle(w, destroy, ev);
else {
Dprint("DestroyWindow(%ux) (no handler)\n", (uint)ev->window);
Dprint(DGeneric, "DestroyWindow(%ux) (no handler)\n", (uint)ev->window);
if((c = win2client(ev->window)))
fprint(2, "Badness: Unhandled DestroyNotify: "
"Client: %p, Window: %W, Name: %s\n", c, &c->w, c->name);
@ -102,7 +110,7 @@ enternotify(XEvent *e) {
handle(w, enter, ev);
else if(ev->window == scr.root.w) {
sel_screen = True;
draw_frames();
frame_draw_all();
}
}
@ -113,15 +121,15 @@ leavenotify(XEvent *e) {
ev = &e->xcrossing;
if((ev->window == scr.root.w) && !ev->same_screen) {
sel_screen = True;
draw_frames();
frame_draw_all();
}
}
void
print_focus(Client *c, char *to) {
Dprint("screen->focus: %p[%C] => %p[%C]\n",
print_focus(Client *c, const char *to) {
Dprint(DFocus, "screen->focus: %p[%C] => %p[%C]\n",
screen->focus, screen->focus, c, c);
Dprint("\t%s => %s\n", clientname(screen->focus), to);
Dprint(DFocus, "\t%s => %s\n", clientname(screen->focus), to);
}
static void
@ -162,7 +170,7 @@ focusin(XEvent *e) {
print_focus(&c_magic, "<magic>");
screen->focus = &c_magic;
if(c->sel)
draw_frame(c->sel);
frame_draw(c->sel);
}
}
}
@ -234,11 +242,11 @@ maprequest(XEvent *e) {
if(wa.override_redirect) {
XSelectInput(display, ev->window,
(StructureNotifyMask | PropertyChangeMask));
(StructureNotifyMask | PropertyChangeMask));
return;
}
if(!win2client(ev->window))
create_client(ev->window, &wa);
client_create(ev->window, &wa);
}
static void
@ -287,6 +295,7 @@ void (*handler[LASTEvent]) (XEvent *) = {
[ButtonPress] = buttonpress,
[ButtonRelease] = buttonrelease,
[ConfigureRequest] = configurerequest,
[ClientMessage] = clientmessage,
[DestroyNotify] = destroynotify,
[EnterNotify] = enternotify,
[Expose] = expose,

388
cmd/wmii/ewmh.c Normal file
View File

@ -0,0 +1,388 @@
/* Copyright ©2007 Kris Maglione <fbsdaemon@gmail.com>
* See LICENSE file for license details.
*/
#include <assert.h>
#include "dat.h"
#include "fns.h"
Window *ewmhwin;
#define Net(x) ("_NET_" x)
#define Action(x) ("_NET_WM_ACTION_" x)
#define State(x) ("_NET_WM_STATE_" x)
#define Type(x) ("_NET_WM_WINDOW_TYPE_" x)
#define NET(x) xatom(Net(x))
#define ACTION(x) xatom(Action(x))
#define STATE(x) xatom(State(x))
#define TYPE(x) xatom(Type(x))
void
ewmh_init(void) {
WinAttr wa;
char myname[] = "wmii";
long win[1];
ewmhwin = createwindow(&scr.root,
Rect(0, 0, 1, 1), 0 /*depth*/,
InputOnly, &wa, 0);
win[0] = ewmhwin->w;
changeprop_long(&scr.root, Net("SUPPORTING_WM_CHECK"), "WINDOW",
win, 1);
changeprop_long(ewmhwin, Net("SUPPORTING_WM_CHECK"), "WINDOW",
win, 1);
changeprop_string(ewmhwin, Net("WM_NAME"), myname);
changeprop_long(&scr.root, Net("DESKTOP_VIEWPORT"), "CARDINAL",
(long[]){0, 0}, 2);
long supported[] = {
/* Misc */
NET("SUPPORTED"),
/* Root Properties */
NET("ACTIVE_WINDOW"),
NET("CURRENT_DESKTOP"),
/* Client Properties */
NET("WM_NAME"),
NET("WM_STRUT_PARTIAL"),
NET("WM_DESKTOP"),
NET("FRAME_EXTENTS"),
/* States */
NET("WM_STATE"),
STATE("DEMANDS_ATTENTION"),
STATE("FULLSCREEN"),
STATE("SHADED"),
/* Window Types */
NET("WM_WINDOW_TYPE"),
TYPE("DIALOG"),
TYPE("DOCK"),
TYPE("NORMAL"),
TYPE("SPLASH"),
/* Actions */
NET("WM_ALLOWED_ACTIONS"),
ACTION("FULLSCREEN"),
/* Desktops */
NET("DESKTOP_NAMES"),
NET("NUMBER_OF_DESKTOPS"),
/* Client List */
NET("CLIENT_LIST"),
NET("CLIENT_LIST_STACKING"),
};
changeprop_long(&scr.root, Net("SUPPORTED"), "ATOM", supported, nelem(supported));
}
void
ewmh_updateclientlist(void) {
Client *c;
long *list;
int i;
i = 0;
for(c=client; c; c=c->next)
i++;
list = emalloc(i * sizeof *list);
for(c=client, i=0; c; c=c->next)
list[i++] = c->w.w;
changeprop_long(&scr.root, Net("CLIENT_LIST"), "WINDOW", list, i);
}
void
ewmh_updatestacking(void) {
Vector_long vec;
Frame *f;
Area *a;
View *v;
vector_linit(&vec);
for(v=view; v; v=v->next)
for(f=v->area->stack; f; f=f->snext)
if(f->client->sel == f)
vector_lpush(&vec, f->client->w.w);
for(v=view; v; v=v->next)
for(a=v->area->next; a; a=a->next)
for(f=a->frame; f; f=f->anext)
if(f->client->sel == f)
vector_lpush(&vec, f->client->w.w);
changeprop_long(&scr.root, Net("CLIENT_LIST_STACKING"), "WINDOW", vec.ary, vec.n);
vector_lfree(&vec);
}
void
ewmh_initclient(Client *c) {
long allowed[] = {
ACTION("FULLSCREEN"),
};
changeprop_long(&c->w, Net("WM_ALLOWED_ACTIONS"), "ATOM",
allowed, nelem(allowed));
ewmh_getwintype(c);
ewmh_updateclientlist();
}
void
ewmh_destroyclient(Client *c) {
ewmh_updateclientlist();
}
void
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);
}
void
ewmh_getwintype(Client *c) {
struct {
char* name;
long mask;
Atom atom;
} static pairs[] = {
{Type("DESKTOP"), TypeDesktop},
{Type("DOCK"), TypeDock},
{Type("TOOLBAR"), TypeToolbar},
{Type("MENU"), TypeMenu},
{Type("UTILITY"), TypeUtility},
{Type("SPLASH"), TypeSplash},
{Type("DIALOG"), TypeDialog},
{Type("NORMAL"), TypeNormal},
{0, }
}, *pair;
Atom actual, atom;
long *types;
long mask;
ulong n;
int i;
if(!pairs[0].atom)
for(pair=pairs; pair->name; pair++)
pair->atom = xatom(pair->name);
n = getproperty(&c->w, Net("WM_WINDOW_TYPE"), "ATOM", &actual,
0L, (void*)&types, nelem(types));
Dprint(DEwmh, "ewmh_getwintype(%C) actual = %A; n = %d\n", c, actual, n);
if(actual != xatom("ATOM"))
return;
mask = 0;
for(i=0; i < n; i++) {
atom = types[i];
Dprint(DEwmh, "\ttypes[%d] = \"%A\"\n", i, types[i], types[i]);
for(pair=pairs; pair->name; pair++)
if(pair->atom == atom) {
mask |= pair->mask;
break;
}
}
c->w.ewmh.type = mask;
if(mask & TypeDock) {
c->borderless = 1;
c->titleless = 1;
}
}
void
ewmh_getstrut(Client *c) {
enum {
Left, Right, Top, Bottom,
LeftMin, LeftMax,
RithtMin, RightMax,
TopMin, TopMax,
BottomMin, BottomMax
};
Atom actual;
long strut[12];
ulong n;
n = getproperty(&c->w, Net("WM_STRUT_PARTIAL"), "CARDINAL", &actual,
0L, (void*)&strut, nelem(strut));
if(n != nelem(strut))
return;
if(actual != xatom("ATOM"))
return;
}
int
ewmh_clientmessage(XClientMessageEvent *e) {
Client *c;
View *v;
long *l;
int msg, action, i;
l = e->data.l;
msg = e->message_type;
Dprint(DEwmh, "ClientMessage: %A\n", msg);
if(msg == NET("WM_STATE")) {
enum {
StateUnset,
StateSet,
StateToggle,
};
if(e->format != 32)
return -1;
c = win2client(e->window);
if(c == nil)
return 0;
switch(l[0]) {
case StateUnset: action = Off; break;
case StateSet: action = On; break;
case StateToggle: action = Toggle; break;
default:
return -1;
}
Dprint(DEwmh, "\tAction: %s\n", TOGGLE(action));
for(i = 1; i <= 2; i++) {
if(l[i] == 0)
break;
Dprint(DEwmh, "\tl[%d] = %A\n", i, l[i]);
if(l[i] == STATE("FULLSCREEN"))
fullscreen(c, action);
else
if(l[i] == STATE("DEMANDS_ATTENTION"))
client_seturgent(c, action, false);
}
return 1;
}else
if(msg == NET("ACTIVE_WINDOW")) {
if(e->format != 32)
return -1;
if(l[0] != 2)
return 1;
c == win2client(e->window);
if(c == nil)
return 1;
focus(c, true);
return 1;
}else
if(msg == NET("CURRENT_DESKTOP")) {
print("\t%ld\n", l[0]);
if(e->format != 32)
return -1;
print("\t%ld\n", l[0]);
for(v=view, i=l[0]; v; v=v->next, i--)
if(i == 0)
break;
print("\t%d\n", i);
if(i == 0)
view_select(v->name);
return 1;
}
return 0;
}
void
ewmh_framesize(Client *c) {
Rectangle r;
Frame *f;
f = c->sel;
r.min.x = f->crect.min.x;
r.min.y = f->crect.min.y;
r.max.x = f->r.max.x - f->crect.max.x;
r.max.y = f->r.max.y - f->crect.max.y;
long extents[] = {
r.min.x, r.max.x,
r.min.y, r.max.y,
};
changeprop_long(&c->w, Net("FRAME_EXTENTS"), "CARDINAL",
extents, nelem(extents));
}
void
ewmh_updatestate(Client *c) {
long state[16];
Frame *f;
int i;
f = c->sel;
if(f->view != screen->sel)
return;
i = 0;
if(f->collapsed)
state[i++] = STATE("SHADED");
if(c->fullscreen)
state[i++] = STATE("FULLSCREEN");
if(c->urgent)
state[i++] = STATE("DEMANDS_ATTENTION");
assert(i < nelem(state)); /* Can't happen. */
if(i > 0)
changeprop_long(&c->w, Net("WM_STATE"), "ATOM", state, i);
else
delproperty(&c->w, Net("WM_STATE"));
}
/* Views */
void
ewmh_updateviews(void) {
View *v;
char **tags;
long i;
if(starting)
return;
for(v=view, i=0; v; v=v->next)
i++;
tags = emalloc((i + 1) * sizeof *tags);
for(v=view, i=0; v; v=v->next)
tags[i++] = v->name;
tags[i] = nil;
changeprop_textlist(&scr.root, Net("DESKTOP_NAMES"), "UTF8_STRING", tags);
changeprop_long(&scr.root, Net("NUMBER_OF_DESKTOPS"), "CARDINAL", &i, 1);
ewmh_updateview();
ewmh_updateclients();
}
static int
viewidx(View *v) {
View *vp;
int i;
for(vp=view, i=0; vp; vp=vp->next, i++)
if(vp == v)
break;
assert(vp);
return i;
}
void
ewmh_updateview(void) {
long i;
if(starting)
return;
i = viewidx(screen->sel);
changeprop_long(&scr.root, Net("CURRENT_DESKTOP"), "CARDINAL", &i, 1);
}
void
ewmh_updateclient(Client *c) {
long i;
i = -1;
if(c->sel)
i = viewidx(c->sel->view);
changeprop_long(&c->w, Net("WM_DESKTOP"), "CARDINAL", &i, 1);
}
void
ewmh_updateclients(void) {
Client *c;
if(starting)
return;
for(c=client; c; c=c->next)
ewmh_updateclient(c);
}

View File

@ -3,244 +3,225 @@
*/
#ifdef VARARGCK
# pragma varargck argpos write_event 1
# pragma varargck argpos event 1
#
# pragma varargck type "C" Client*
# pragma varargck type "W" Window*
# pragma varargck type "P" Point
# pragma varargck type "R" Rectangle
# 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 */
char *area_name(Area *a);
uint area_idx(Area *a);
Area *create_area(View*, Area *pos, uint w);
void destroy_area(Area*);
Area *area_of_id(View*, ushort id);
void focus_area(Area*);
void send_to_area(Area*, Frame*);
void attach_to_area(Area*, Frame*);
void detach_from_area(Frame*);
Client *area_selclient(Area*);
void area_attach(Area*, Frame*);
Area* area_create(View*, Area *pos, uint w);
void area_destroy(Area*);
void area_detach(Frame*);
void area_focus(Area*);
uint area_idx(Area*);
void area_moveto(Area*, Frame*);
char* area_name(Area*);
Client* area_selclient(Area*);
/* bar.c */
void initbar(WMScreen *s);
Bar *create_bar(Bar **b_link, char *name);
void destroy_bar(Bar **b_link, Bar*);
void draw_bar(WMScreen *s);
void resize_bar(WMScreen *s);
Bar *bar_of_name(Bar *b_link, const char *name);
Bar* bar_create(Bar**, const char*);
void bar_destroy(Bar**, Bar*);
void bar_draw(WMScreen*);
Bar* bar_find(Bar*, const char*);
void bar_init(WMScreen*);
void bar_resize(WMScreen*);
/* client.c */
Client *create_client(XWindow, XWindowAttributes*);
void destroy_client(Client*);
void configure_client(Client*);
void update_class(Client *c);
void prop_client(Client *c, Atom);
void kill_client(Client*);
void gravitate_client(Client*, Bool invert);
void map_client(Client*);
void unmap_client(Client*, int state);
int map_frame(Client*);
int unmap_frame(Client*);
Rectangle gravclient(Client*, Rectangle);
void fullscreen(Client*, Bool);
void set_urgent(Client *, Bool urgent, Bool write);
void set_cursor(Client*, Cursor);
void focus_frame(Frame*, Bool restack);
void reparent_client(Client*, Window*, Point);
void manage_client(Client*);
void focus(Client*, Bool restack);
void focus_client(Client*);
void resize_client(Client*, Rectangle*);
void apply_sizehints(Client*, Rectangle*, Bool floating, Bool frame, Align sticky);
void move_client(Client*, char *arg);
void size_client(Client*, char *arg);
Client *selclient(void);
Client *win2client(XWindow);
int Cfmt(Fmt *f);
char *clientname(Client*);
void apply_rules(Client*);
void apply_tags(Client*, const char*);
int Cfmt(Fmt *f);
void apply_rules(Client*);
void apply_tags(Client*, const char*);
void client_configure(Client*);
Client* client_create(XWindow, XWindowAttributes*);
void client_destroy(Client*);
void client_focus(Client*);
void client_kill(Client*);
void client_manage(Client*);
void client_map(Client*);
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_unmap(Client*, int state);
Frame* client_viewframe(Client *c, View *v);
char* clientname(Client*);
void focus(Client*, bool restack);
void fullscreen(Client*, int);
int map_frame(Client*);
Client* selclient(void);
int unmap_frame(Client*);
void update_class(Client*);
Client* win2client(XWindow);
Rectangle client_grav(Client*, Rectangle);
/* column.c */
void update_divs(void);
void draw_div(Divide*);
void setdiv(Divide*, int x);
void arrange_column(Area*, Bool dirty);
void resize_column(Area*, int w);
void resize_colframe(Frame*, Rectangle*);
int str2colmode(const char *str);
char *colmode2str(int i);
Area *new_column(View*, Area *pos, uint w);
char* colmode2str(int);
int str2colmode(const char*);
void column_arrange(Area*, bool dirty);
Area* column_new(View*, Area *, uint);
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);
/* event.c */
void dispatch_event(XEvent*);
void check_x_event(IxpConn*);
uint flushevents(long even_mask, Bool dispatch);
void print_focus(Client *c, char *to);
void check_x_event(IxpConn*);
void dispatch_event(XEvent*);
uint flushevents(long, bool dispatch);
void print_focus(Client*, const char*);
/* ewmh.c */
int ewmh_clientmessage(XClientMessageEvent*);
void ewmh_destroyclient(Client*);
void ewmh_framesize(Client*);
void ewmh_getstrut(Client*);
void ewmh_getwintype(Client*);
void ewmh_init(void);
void ewmh_initclient(Client*);
void ewmh_prop(Client*, Atom);
void ewmh_updateclient(Client*);
void ewmh_updateclientlist(void);
void ewmh_updateclients(void);
void ewmh_updatestacking(void);
void ewmh_updatestate(Client*);
void ewmh_updateview(void);
void ewmh_updateviews(void);
/* frame.c */
uint frame_idx(Frame *f);
Frame *create_frame(Client*, View*);
void remove_frame(Frame*);
void insert_frame(Frame *pos, Frame*);
void resize_frame(Frame*, Rectangle);
Bool frame_to_top(Frame *f);
void set_frame_cursor(Frame*, Point);
void swap_frames(Frame*, Frame*);
int frame_delta_h(void);
Rectangle frame_hints(Frame*, Rectangle, Align);
Rectangle frame2client(Frame*, Rectangle);
Rectangle client2frame(Frame*, Rectangle);
int ingrabbox(Frame*, int x, int y);
void draw_frame(Frame*);
void draw_frames(void);
void update_frame_widget_colors(Frame*);
Frame* frame_create(Client*, View*);
int frame_delta_h(void);
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_remove(Frame*);
void frame_resize(Frame*, Rectangle);
void frame_setcursor(Frame*, Point);
void frame_swap(Frame*, Frame*);
bool frame_to_top(Frame*);
int ingrabbox_p(Frame*, int x, int y);
void move_focus(Frame*, Frame*);
Rectangle constrain(Rectangle);
Rectangle frame_client2rect(Frame*, Rectangle);
Rectangle frame_hints(Frame*, Rectangle, Align);
Rectangle frame_rect2client(Frame*, Rectangle);
/* fs.c */
void fs_attach(Ixp9Req*);
void fs_clunk(Ixp9Req*);
void fs_create(Ixp9Req*);
void fs_flush(Ixp9Req*);
void fs_freefid(Fid*);
void fs_open(Ixp9Req*);
void fs_read(Ixp9Req*);
void fs_remove(Ixp9Req*);
void fs_stat(Ixp9Req*);
void fs_walk(Ixp9Req*);
void fs_write(Ixp9Req*);
void write_event(char*, ...);
void fs_attach(Ixp9Req*);
void fs_clunk(Ixp9Req*);
void fs_create(Ixp9Req*);
void fs_flush(Ixp9Req*);
void fs_freefid(Fid*);
void fs_open(Ixp9Req*);
void fs_read(Ixp9Req*);
void fs_remove(Ixp9Req*);
void fs_stat(Ixp9Req*);
void fs_walk(Ixp9Req*);
void fs_write(Ixp9Req*);
void event(const char*, ...);
/* geom.c */
Bool ptinrect(Point, Rectangle);
Align quadrant(Rectangle, Point);
Cursor cursor_of_quad(Align);
Align get_sticky(Rectangle src, Rectangle dst);
Cursor quad_cursor(Align);
Align get_sticky(Rectangle src, Rectangle dst);
bool rect_haspoint_p(Point, Rectangle);
Align quadrant(Rectangle, Point);
/* key.c */
void kpress(XWindow, ulong mod, KeyCode);
void update_keys(void);
void init_lock_keys(void);
ulong str2modmask(char*);
void init_lock_keys(void);
void kpress(XWindow, ulong mod, KeyCode);
ulong str2modmask(const char*);
void update_keys(void);
/* map.c */
MapEnt* mapget(Map*, ulong, int create);
MapEnt* hashget(Map*, char*, int create);
void* maprm(Map*, ulong);
void* hashrm(Map*, char*);
MapEnt* hash_get(Map*, const char*, int create);
void* hash_rm(Map*, const char*);
MapEnt* map_get(Map*, ulong, int create);
void* map_rm(Map*, ulong);
/* message.c */
char *getword(IxpMsg*);
int getulong(char*, ulong*);
int getlong(char*, long*);
Area *strarea(View*, char*);
char *message_view(View*, IxpMsg*);
char *parse_colors(IxpMsg*, CTuple*);
char *message_root(void*, IxpMsg*);
char *read_root_ctl(void);
char *message_client(Client*, IxpMsg*);
char *select_area(Area*, IxpMsg*);
char *send_client(View*, IxpMsg*, Bool swap);
int getlong(const char*, long*);
int getulong(const char*, ulong*);
char* message_client(Client*, IxpMsg*);
char* message_root(void*, IxpMsg*);
char* message_view(View*, IxpMsg*);
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);
Area* strarea(View*, const char*);
/* mouse.c */
void mouse_resizecol(Divide*);
void do_mouse_resize(Client*, Bool opaque, Align);
void grab_mouse(XWindow, ulong mod, ulong button);
void ungrab_mouse(XWindow, ulong mod, uint button);
Align snap_rect(Rectangle *rects, int num, Rectangle *current, Align *mask, int snapw);
void grab_button(XWindow, uint button, ulong mod);
void mouse_resize(Client*, bool opaque, Align);
void mouse_resizecol(Divide*);
void grab_button(XWindow, uint button, ulong mod);
Align snap_rect(Rectangle *rects, int num, Rectangle *current, Align *mask, int snapw);
/* rule.c */
void update_rules(Rule**, const char*);
void trim(char *str, const char *chars);
void trim(char *str, const char *chars);
void update_rules(Rule**, const char*);
/* view.c */
void arrange_view(View*);
void scale_view(View*, int w);
View *get_view(const char*);
View *create_view(const char*);
void focus_view(WMScreen*, View*);
void update_client_views(Client*, char**);
Rectangle *rects_of_view(View*, uint *num, Frame *ignore);
View *view_of_id(ushort);
Frame *view_clientframe(View *v, Client *c);
void select_view(const char*);
void attach_to_view(View*, Frame*);
Client *view_selclient(View*);
char *message_view(View *v, IxpMsg *m);
void restack_view(View*);
uchar *view_index(View*);
uchar *view_ctl(View *v);
void destroy_view(View*);
void update_views(void);
uint newcolw(View*, int i);
void view_arrange(View*);
void view_attach(View*, Frame*);
View* view_create(const char*);
char* view_ctl(View *v);
void view_destroy(View*);
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 view_setclient(Client*, char**);
void view_update_all(void);
Rectangle* view_rects(View*, uint *num, Frame *ignore);
/* wm.c */
int win_proto(Window);
/* utf.c */
char* toutf8(const char*);
char* toutf8n(const char*, size_t);
/* x11.c */
XRectangle XRect(Rectangle);
int eqrect(Rectangle, Rectangle);
int eqpt(Point, Point);
Point addpt(Point, Point);
Point subpt(Point, Point);
Point mulpt(Point p, Point q);
Point divpt(Point, Point);
Rectangle insetrect(Rectangle, int);
Rectangle rectaddpt(Rectangle, Point);
Rectangle rectsubpt(Rectangle, Point);
void initdisplay(void);
Image * allocimage(int w, int h, int depth);
void freeimage(Image *);
Window *createwindow(Window *parent, Rectangle, int depth, uint class, WinAttr*, int valuemask);
void reparentwindow(Window*, Window*, Point);
void destroywindow(Window*);
void setwinattr(Window*, WinAttr*, int valmask);
void reshapewin(Window*, Rectangle);
void movewin(Window*, Point);
int mapwin(Window*);
int unmapwin(Window*);
void lowerwin(Window*);
void raisewin(Window*);
Handlers* sethandler(Window*, Handlers*);
Window* findwin(XWindow);
uint winprotocols(Window*);
void setshapemask(Window *dst, Image *src, Point);
void border(Image *dst, Rectangle, int w, ulong col);
void fill(Image *dst, Rectangle, ulong col);
void drawpoly(Image *dst, Point *pt, int np, int cap, int w, ulong col);
void fillpoly(Image *dst, Point *pt, int np, ulong col);
void drawline(Image *dst, Point p1, Point p2, int cap, int w, ulong col);
void drawstring(Image *dst, Font *font, Rectangle, Align align, char *text, ulong col);
void copyimage(Image *dst, Rectangle, Image *src, Point p);
Bool namedcolor(char *name, ulong*);
Bool loadcolor(CTuple*, char*);
Font * loadfont(char*);
void freefont(Font*);
uint textwidth_l(Font*, char*, uint len);
uint textwidth(Font*, char*);
uint labelh(Font*);
Atom xatom(char*);
void freestringlist(char**);
ulong getproperty(Window *w, char *prop, char *type, Atom *actual, ulong offset, uchar **ret, ulong length);
char *gettextproperty(Window*, char*);
int gettextlistproperty(Window *w, char *name, char **ret[]);
void changeproperty(Window*, char *prop, char *type, int width, uchar *data, int n);
void changeprop_char(Window *w, char *prop, char *type, char data[], int len);
void changeprop_short(Window *w, char *prop, char *type, short data[], int len);
void changeprop_long(Window *w, char *prop, char *type, long data[], int len);
void setfocus(Window*, int mode);
Point querypointer(Window*);
void warppointer(Point);
Point translate(Window*, Window*, Point);
int grabpointer(Window*, Window *confine, Cursor, int mask);
void ungrabpointer(void);
Rectangle gravitate(Rectangle dst, Rectangle src, Point grav);
Rectangle sizehint(WinHints*, Rectangle);
void sethints(Window*);
char* toutf8n(char*, size_t);
char* toutf8(char*);

View File

@ -3,7 +3,6 @@
*/
#include "dat.h"
#include <math.h>
#include <stdio.h>
#include "fns.h"
uint
@ -17,8 +16,8 @@ frame_idx(Frame *f) {
return i;
}
Frame *
create_frame(Client *c, View *v) {
Frame*
frame_create(Client *c, View *v) {
static ushort id = 1;
Frame *f;
@ -32,7 +31,7 @@ create_frame(Client *c, View *v) {
f->r = c->sel->r;
}
else{
f->r = client2frame(f, gravclient(c, ZR));
f->r = frame_client2rect(f, client_grav(c, ZR));
f->revert = f->r;
c->sel = f;
}
@ -42,7 +41,7 @@ create_frame(Client *c, View *v) {
}
void
remove_frame(Frame *f) {
frame_remove(Frame *f) {
Area *a;
a = f->area;
@ -65,7 +64,7 @@ remove_frame(Frame *f) {
}
void
insert_frame(Frame *pos, Frame *f) {
frame_insert(Frame *pos, Frame *f) {
Area *a;
a = f->area;
@ -90,7 +89,7 @@ insert_frame(Frame *pos, Frame *f) {
}
}
Bool
bool
frame_to_top(Frame *f) {
Area *a;
@ -115,7 +114,7 @@ frame_to_top(Frame *f) {
/* Handlers */
static void
bup_event(Window *w, XButtonEvent *e) {
write_event("ClientClick %C %d\n", w->aux, e->button);
event("ClientClick %C %d\n", w->aux, e->button);
}
static void
@ -129,15 +128,15 @@ bdown_event(Window *w, XButtonEvent *e) {
if((e->state & def.mod) == def.mod) {
switch(e->button) {
case Button1:
do_mouse_resize(c, False, CENTER);
focus(c, True);
mouse_resize(c, False, CENTER);
focus(c, false);
frame_to_top(f);
focus(c, True);
focus(c, false); /* Blech */
break;
case Button3:
do_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_to_top(f);
focus(c, True);
focus(c, false);
break;
default:
XAllowEvents(display, ReplayPointer, e->time);
@ -148,24 +147,24 @@ bdown_event(Window *w, XButtonEvent *e) {
}else{
if(e->button == Button1) {
if(frame_to_top(f))
restack_view(f->view);
else if(ptinrect(Pt(e->x, e->y), f->grabbox))
do_mouse_resize(c, True, CENTER);
view_restack(f->view);
else if(rect_haspoint_p(Pt(e->x, e->y), f->grabbox))
mouse_resize(c, True, CENTER);
else if(f->area->floating)
if(!e->subwindow && !ptinrect(Pt(e->x, e->y), f->titlebar))
do_mouse_resize(c, False, quadrant(f->r, Pt(e->x_root, e->y_root)));
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)));
if(f->client != selclient())
focus(c, True);
focus(c, false);
}
if(e->subwindow)
XAllowEvents(display, ReplayPointer, e->time);
else {
/* Ungrab so a menu can receive events before the button is released */
XUngrabPointer(display, e->time);
XSync(display, False);
sync();
write_event("ClientMouseDown %C %d\n", f->client, e->button);
event("ClientMouseDown %C %d\n", f->client, e->button);
}
}
}
@ -177,12 +176,12 @@ enter_event(Window *w, XCrossingEvent *e) {
c = w->aux;
f = c->sel;
if(screen->focus != c) {
Dprint("enter_notify(f) => %s\n", f->client->name);
if(screen->focus != c || selclient() != c) {
Dprint(DGeneric, "enter_notify(f) => %s\n", f->client->name);
if(f->area->floating || !f->collapsed)
focus(f->client, False);
focus(f->client, false);
}
set_frame_cursor(f, Pt(e->x, e->y));
frame_setcursor(f, Pt(e->x, e->y));
}
static void
@ -193,7 +192,7 @@ expose_event(Window *w, XExposeEvent *e) {
c = w->aux;
if(c->sel)
draw_frame(c->sel);
frame_draw(c->sel);
else
fprint(2, "Badness: Expose event on a client frame which shouldn't be visible: %C\n",
c);
@ -204,7 +203,7 @@ motion_event(Window *w, XMotionEvent *e) {
Client *c;
c = w->aux;
set_frame_cursor(c->sel, Pt(e->x, e->y));
frame_setcursor(c->sel, Pt(e->x, e->y));
}
Handlers framehandler = {
@ -216,7 +215,7 @@ Handlers framehandler = {
};
Rectangle
frame2client(Frame *f, Rectangle r) {
frame_rect2client(Frame *f, Rectangle r) {
if(f == nil || f->area == nil || f->area->floating) {
r.max.x -= def.border * 2;
r.max.y -= frame_delta_h();
@ -238,7 +237,7 @@ frame2client(Frame *f, Rectangle r) {
}
Rectangle
client2frame(Frame *f, Rectangle r) {
frame_client2rect(Frame *f, Rectangle r) {
if(f == nil || f->area == nil || f->area->floating) {
r.max.x += def.border * 2;
r.max.y += frame_delta_h();
@ -258,10 +257,11 @@ client2frame(Frame *f, Rectangle r) {
}
void
resize_frame(Frame *f, Rectangle r) {
frame_resize(Frame *f, Rectangle r) {
Align stickycorner;
Point pt;
Client *c;
int collapsed;
c = f->client;
stickycorner = get_sticky(f->r, r);
@ -276,9 +276,11 @@ resize_frame(Frame *f, Rectangle r) {
else
f->r = r;
f->crect = frame2client(f, f->crect);
f->crect = frame_rect2client(f, f->crect);
f->crect = rectsubpt(f->crect, f->crect.min);
collapsed = f->collapsed;
if(!f->area->floating && f->area->mode == Coldefault) {
if(Dy(f->r) < 2 * labelh(def.font))
f->collapsed = True;
@ -296,6 +298,9 @@ resize_frame(Frame *f, Rectangle r) {
f->crect = f->r;
}
if(collapsed != f->collapsed)
ewmh_updatestate(c);
pt = ZP;
if(!f->client->borderless || !f->area->floating)
pt.y += 1;
@ -305,7 +310,7 @@ resize_frame(Frame *f, Rectangle r) {
if(f->area->floating) {
if(c->fullscreen) {
f->crect = screen->r;
f->r = client2frame(f, f->crect);
f->r = frame_client2rect(f, f->crect);
pt.x = (Dx(f->r) - Dx(f->crect)) / 2;
f->r = rectsubpt(f->r, pt);
}else
@ -316,34 +321,34 @@ resize_frame(Frame *f, Rectangle r) {
}
void
set_frame_cursor(Frame *f, Point pt) {
frame_setcursor(Frame *f, Point pt) {
Rectangle r;
Cursor cur;
if(f->area->floating
&& !ptinrect(pt, f->titlebar)
&& !ptinrect(pt, f->crect)) {
&& !rect_haspoint_p(pt, f->titlebar)
&& !rect_haspoint_p(pt, f->crect)) {
r = rectsubpt(f->r, f->r.min);
cur = cursor_of_quad(quadrant(r, pt));
set_cursor(f->client, cur);
cur = quad_cursor(quadrant(r, pt));
client_setcursor(f->client, cur);
} else
set_cursor(f->client, cursor[CurNormal]);
client_setcursor(f->client, cursor[CurNormal]);
}
void
swap_frames(Frame *fa, Frame *fb) {
frame_swap(Frame *fa, Frame *fb) {
Frame **fp;
Client *c;
if(fa == fb) return;
for(fp = &fa->client->frame; *fp; fp = &(*fp)->cnext)
for(fp = &fa->client->frame; *fp; fp = &fp[0]->cnext)
if(*fp == fa) break;
*fp = (*fp)->cnext;
fp[0] = fp[0]->cnext;
for(fp = &fb->client->frame; *fp; fp = &(*fp)->cnext)
for(fp = &fb->client->frame; *fp; fp = &fp[0]->cnext)
if(*fp == fb) break;
*fp = (*fp)->cnext;
fp[0] = fp[0]->cnext;
c = fa->client;
fa->client = fb->client;
@ -356,33 +361,49 @@ swap_frames(Frame *fa, Frame *fb) {
c->frame = fa;
if(c->sel && c->sel->view == screen->sel)
focus_view(screen, c->sel->view);
view_focus(screen, c->sel->view);
}
void
focus_frame(Frame *f, Bool restack) {
move_focus(Frame *old_f, Frame *f) {
int noinput;
noinput = (old_f && old_f->client->noinput) ||
(f && f->client->noinput) ||
screen->hasgrab != &c_root;
if(noinput) {
if(old_f)
frame_draw(old_f);
if(f)
frame_draw(f);
}
}
void
frame_focus(Frame *f) {
View *v;
Area *a, *old_a;
Frame *old_f;
a = f->area;
v = f->view;
old_a = v->sel;
old_f = old_a->sel;
a->sel = f;
if(a != old_a)
focus_area(f->area);
area_focus(f->area);
if(v != screen->sel)
if(v != screen->sel || a != v->sel)
return;
focus_client(f->client);
move_focus(old_f, f);
client_focus(f->client);
if(!a->floating && ((a->mode == Colstack) || (a->mode == Colmax)))
arrange_column(a, False);
if(restack)
restack_view(v);
column_arrange(a, False);
}
int
@ -391,7 +412,7 @@ frame_delta_h(void) {
}
void
draw_frame(Frame *f) {
frame_draw(Frame *f) {
Rectangle r, fr;
CTuple *col;
Frame *tf;
@ -399,7 +420,8 @@ draw_frame(Frame *f) {
if(f->view != screen->sel)
return;
if(f->client == screen->focus)
if(f->client == screen->focus
|| f->client == selclient())
col = &def.focuscolor;
else
col = &def.normcolor;
@ -423,6 +445,11 @@ draw_frame(Frame *f) {
f->titlebar = insetrect(r, 3);
f->titlebar.max.y += 3;
/* Odd state of focus. */
if(f->client != selclient() && col == &def.focuscolor)
border(screen->ibuf, insetrect(r, 1),
1, def.normcolor.bg);
/* grabbox */
r.min = Pt(2, 2);
r.max.x = r.min.x + def.font->height - 3;
@ -433,6 +460,12 @@ draw_frame(Frame *f) {
fill(screen->ibuf, r, col->fg);
border(screen->ibuf, r, 1, col->border);
/* Odd state of focus. */
if(f->client != screen->focus && col == &def.focuscolor)
border(screen->ibuf, insetrect(r, -1),
1, def.normcolor.bg);
/* Label */
r.min.x = r.max.x;
r.max.x = fr.max.x;
r.min.y = 0;
@ -440,18 +473,26 @@ draw_frame(Frame *f) {
drawstring(screen->ibuf, def.font, r, WEST,
f->client->name, col->fg);
/* 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. Lovely, no?
* 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.
* This is why we love X11 so.
*/
XSetWindowBackgroundPixmap(display, f->client->framewin->w, None);
copyimage(f->client->framewin, fr, screen->ibuf, ZP);
XSync(display, False);
sync();
}
void
draw_frames(void) {
frame_draw_all(void) {
Client *c;
for(c=client; c; c=c->next)
if(c->sel && c->sel->view == screen->sel)
draw_frame(c->sel);
frame_draw(c->sel);
}
Rectangle

View File

@ -5,9 +5,6 @@
#include <assert.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "fns.h"
@ -110,7 +107,7 @@ dirtab_clients[]={{".", QTDIR, FsDClients, 0500|DMDIR },
{nil}},
dirtab_client[]= {{".", QTDIR, FsDClient, 0500|DMDIR },
{"ctl", QTAPPEND, FsFCctl, 0600|DMAPPEND },
{"label", QTFILE, FsFClabel, 0600 },
{"label", QTFILE, FsFClabel, 0600 },
{"tags", QTFILE, FsFCtags, 0600 },
{"props", QTFILE, FsFprops, 0400 },
{nil}},
@ -185,8 +182,9 @@ write_buf(Ixp9Req *r, char *buf, uint len) {
/* This should be moved to libixp */
static void
write_to_buf(Ixp9Req *r, void *buf, uint *len, uint max) {
write_to_buf(Ixp9Req *r, char **buf, uint *len, uint max) {
uint offset, count;
char *p;
offset = (r->fid->omode&OAPPEND) ? *len : r->ifcall.offset;
if(offset > *len || r->ifcall.count == 0) {
@ -199,15 +197,14 @@ write_to_buf(Ixp9Req *r, void *buf, uint *len, uint max) {
count = max - offset;
*len = offset + count;
if(max == 0)
*buf = erealloc((void*)*buf, *len + 1);
if(max == 0) {
*(void **)buf = erealloc(*(void **)buf, *len + 1);
buf = *(void **)buf;
}
p = *buf;
memcpy((uchar*)buf + offset, r->ifcall.data, count);
memcpy(p+offset, r->ifcall.data, count);
r->ofcall.count = count;
((char *)buf)[offset+count] = '\0';
p[offset+count] = '\0';
}
/* This should be moved to libixp */
@ -228,7 +225,7 @@ data_to_cstring(Ixp9Req *r) {
typedef char* (*MsgFunc)(void*, IxpMsg*);
static char *
static char*
message(Ixp9Req *r, MsgFunc fn) {
char *err, *s, *p, c;
FileId *f;
@ -274,7 +271,7 @@ respond_event(Ixp9Req *r) {
}
void
write_event(char *format, ...) {
event(const char *format, ...) {
uint len, slen;
va_list ap;
FidLink *f;
@ -458,7 +455,7 @@ LastItem:
return ret;
}
static Bool
static bool
verify_file(FileId *f) {
FileId *nf;
int ret;
@ -583,7 +580,7 @@ fs_stat(Ixp9Req *r) {
m = ixp_message(buf, size, MsgPack);
ixp_pstat(&m, &s);
r->ofcall.stat = m.data;
r->ofcall.stat = (uchar*)m.data;
respond(r, nil);
}
@ -660,7 +657,7 @@ fs_read(Ixp9Req *r) {
respond(r, nil);
return;
case FsFRctl:
buf = read_root_ctl();
buf = root_readctl();
write_buf(r, buf, strlen(buf));
respond(r, nil);
return;
@ -674,13 +671,13 @@ fs_read(Ixp9Req *r) {
respond(r, nil);
return;
case FsFTindex:
buf = (char*)view_index(f->p.view);
buf = view_index(f->p.view);
n = strlen(buf);
write_buf(r, buf, n);
respond(r, nil);
return;
case FsFTctl:
buf = (char*)view_ctl(f->p.view);
buf = view_ctl(f->p.view);
n = strlen(buf);
write_buf(r, buf, n);
respond(r, nil);
@ -694,13 +691,14 @@ fs_read(Ixp9Req *r) {
* This is an assert because this should this should not be called if
* the file is not open for reading.
*/
assert(!"Read called on an unreadable file");
die("Read called on an unreadable file");
}
void
fs_write(Ixp9Req *r) {
FileId *f;
char *errstr;
char *p;
uint i;
if(r->ifcall.count == 0) {
@ -727,7 +725,7 @@ fs_write(Ixp9Req *r) {
case FsFClabel:
data_to_cstring(r);
utfecpy(f->p.client->name, f->p.client->name+sizeof(client->name), r->ifcall.data);
draw_frame(f->p.client->sel);
frame_draw(f->p.client->sel);
update_class(f->p.client);
r->ofcall.count = r->ifcall.count;
respond(r, nil);
@ -740,7 +738,9 @@ fs_write(Ixp9Req *r) {
return;
case FsFBar:
i = strlen(f->p.bar->buf);
write_to_buf(r, f->p.bar->buf, &i, 279);
/* Why the explicit cast? Ask gcc. */
p = f->p.bar->buf;
write_to_buf(r, &p, &i, 279);
r->ofcall.count = i - r->ifcall.offset;
respond(r, nil);
return;
@ -761,9 +761,9 @@ fs_write(Ixp9Req *r) {
return;
case FsFEvent:
if(r->ifcall.data[r->ifcall.count-1] == '\n')
write_event("%.*s", r->ifcall.count, r->ifcall.data);
event("%.*s", (int)r->ifcall.count, r->ifcall.data);
else
write_event("%.*s\n", r->ifcall.count, r->ifcall.data);
event("%.*s\n", (int)r->ifcall.count, r->ifcall.data);
r->ofcall.count = r->ifcall.count;
respond(r, nil);
return;
@ -772,7 +772,7 @@ fs_write(Ixp9Req *r) {
* This is an assert because this function should not be called if
* the file is not open for writing.
*/
assert(!"Write called on an unwritable file");
die("Write called on an unwritable file");
}
void
@ -825,7 +825,7 @@ fs_create(Ixp9Req *r) {
respond(r, Ebadvalue);
return;
}
create_bar(f->p.bar_p, r->ifcall.name);
bar_create(f->p.bar_p, r->ifcall.name);
f = lookup_file(f, r->ifcall.name);
if(!f) {
respond(r, Enofile);
@ -855,8 +855,8 @@ fs_remove(Ixp9Req *r) {
respond(r, Enoperm);
return;
case FsFBar:
destroy_bar(f->next->p.bar_p, f->p.bar);
draw_bar(screen);
bar_destroy(f->next->p.bar_p, f->p.bar);
bar_draw(screen);
respond(r, nil);
break;
}
@ -884,7 +884,7 @@ fs_clunk(Ixp9Req *r) {
update_rules(&f->p.rule->rule, f->p.rule->string);
for(c=client; c; c=c->next)
apply_rules(c);
update_views();
view_update_all();
break;
case FsFKeys:
update_keys();
@ -893,7 +893,7 @@ fs_clunk(Ixp9Req *r) {
p = toutf8(f->p.bar->buf);
m = ixp_message((uchar*)p, strlen(p), 0);
parse_colors(&m, &f->p.bar->col);
msg_parsecolors(&m, &f->p.bar->col);
q = (char*)m.end-1;
while(q >= (char*)m.pos && *q == '\n')
@ -904,13 +904,13 @@ fs_clunk(Ixp9Req *r) {
free(p);
draw_bar(screen);
bar_draw(screen);
break;
case FsFEvent:
for(fl=&peventfid; *fl; fl=&(*fl)->next)
if((*fl)->fid == r->fid) {
ft = *fl;
*fl = (*fl)->next;
for(fl=&peventfid; *fl; fl=&fl[0]->next)
if(fl[0]->fid == r->fid) {
ft = fl[0];
fl[0] = fl[0]->next;
f = ft->fid->aux;
free(f->p.buf);
free(ft);
@ -926,9 +926,9 @@ fs_flush(Ixp9Req *r) {
Ixp9Req **i, **j;
for(i=&peventread; i != &oeventread; i=&oeventread)
for(j=i; *j; j=(Ixp9Req**)&(*j)->aux)
for(j=i; *j; j=(Ixp9Req**)&j[0]->aux)
if(*j == r->oldreq) {
*j = (*j)->aux;
j[0] = j[0]->aux;
respond(r->oldreq, Einterrupted);
goto done;
}

View File

@ -2,11 +2,10 @@
* See LICENSE file for license details.
*/
#include "dat.h"
#include <stdio.h>
#include "fns.h"
Bool
ptinrect(Point pt, Rectangle r) {
bool
rect_haspoint_p(Point pt, Rectangle r) {
return (pt.x >= r.min.x) && (pt.x < r.max.x)
&& (pt.y >= r.min.y) && (pt.y < r.max.y);
}
@ -31,7 +30,7 @@ quadrant(Rectangle r, Point pt) {
}
Cursor
cursor_of_quad(Align align) {
quad_cursor(Align align) {
switch(align) {
case NEAST:
return cursor[CurNECorner];

View File

@ -2,36 +2,38 @@
* See LICENSE file for license details.
*/
#include "dat.h"
#include <string.h>
#include <stdlib.h>
#include <X11/keysym.h>
#include "fns.h"
void
init_lock_keys(void) {
XModifierKeymap *modmap;
KeyCode num_lock;
KeyCode numlock;
static int masks[] = {
ShiftMask, LockMask, ControlMask, Mod1Mask,
Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
ShiftMask, LockMask, ControlMask,
Mod1Mask, Mod2Mask, Mod3Mask,
Mod4Mask, Mod5Mask
};
int i;
num_lock_mask = 0;
numlock_mask = 0;
modmap = XGetModifierMapping(display);
num_lock = XKeysymToKeycode(display, XStringToKeysym("Num_Lock"));
numlock = keycode("Num_Lock");
if(numlock)
if(modmap && modmap->max_keypermod > 0) {
int max = (sizeof(masks) / sizeof(int)) * modmap->max_keypermod;
int max;
max = nelem(masks) * modmap->max_keypermod;
for(i = 0; i < max; i++)
if(num_lock && (modmap->modifiermap[i] == num_lock))
num_lock_mask = masks[i / modmap->max_keypermod];
if(modmap->modifiermap[i] == numlock)
numlock_mask = masks[i / modmap->max_keypermod];
}
XFreeModifiermap(modmap);
valid_mask = 255 & ~(num_lock_mask | LockMask);
valid_mask = 255 & ~(numlock_mask | LockMask);
}
ulong
str2modmask(char *val) {
str2modmask(const char *val) {
ulong mod = 0;
if (strstr(val, "Shift"))
@ -52,38 +54,40 @@ str2modmask(char *val) {
}
static void
grab_key(Key *k) {
grabkey(Key *k) {
XGrabKey(display, k->key, k->mod, scr.root.w,
True, GrabModeAsync, GrabModeAsync);
if(num_lock_mask) {
XGrabKey(display, k->key, k->mod | num_lock_mask, scr.root.w,
if(numlock_mask) {
XGrabKey(display, k->key, k->mod | numlock_mask, scr.root.w,
True, GrabModeAsync, GrabModeAsync);
XGrabKey(display, k->key, k->mod | num_lock_mask | LockMask, scr.root.w,
XGrabKey(display, k->key, k->mod | numlock_mask | LockMask, scr.root.w,
True, GrabModeAsync, GrabModeAsync);
}
XSync(display, False);
sync();
}
static void
ungrab_key(Key *k) {
ungrabkey(Key *k) {
XUngrabKey(display, k->key, k->mod, scr.root.w);
if(num_lock_mask) {
XUngrabKey(display, k->key, k->mod | num_lock_mask, scr.root.w);
XUngrabKey(display, k->key, k->mod | num_lock_mask | LockMask, scr.root.w);
if(numlock_mask) {
XUngrabKey(display, k->key, k->mod | numlock_mask, scr.root.w);
XUngrabKey(display, k->key, k->mod | numlock_mask | LockMask, scr.root.w);
}
XSync(display, False);
sync();
}
static Key *
name2key(const char *name) {
Key *k;
for(k=key; k; k=k->lnext)
if(!strncmp(k->name, name, sizeof(k->name))) break;
return k;
if(!strncmp(k->name, name, sizeof(k->name)))
return k;
return nil;
}
static Key *
get_key(const char *name) {
getkey(const char *name) {
char buf[128];
char *seq[8];
char *kstr;
@ -94,7 +98,7 @@ get_key(const char *name) {
r = nil;
if((k = name2key(name))) {
ungrab_key(k);
ungrabkey(k);
return k;
}
utflcpy(buf, name, sizeof(buf));
@ -139,26 +143,30 @@ next_keystroke(ulong *mod, KeyCode *code) {
}
static void
emulate_key_press(ulong mod, KeyCode key) {
XEvent e;
XWindow client_win;
int revert;
fake_keypress(ulong mod, KeyCode key) {
XKeyEvent e;
Client *c;
XGetInputFocus(display, &client_win, &revert);
e.xkey.type = KeyPress;
e.xkey.time = CurrentTime;
e.xkey.window = client_win;
e.xkey.display = display;
e.xkey.state = mod;
e.xkey.keycode = key;
XSendEvent(display, client_win, True, KeyPressMask, &e);
e.xkey.type = KeyRelease;
XSendEvent(display, client_win, True, KeyReleaseMask, &e);
XSync(display, False);
c = screen->focus;
if(c == nil || c->w.w == 0)
return;
e.time = CurrentTime;
e.window = c->w.w;
e.display = display;
e.state = mod;
e.keycode = key;
e.type = KeyPress;
sendevent(&c->w, true, KeyPressMask, (XEvent*)&e);
e.type = KeyRelease;
sendevent(&c->w, true, KeyReleaseMask, (XEvent*)&e);
sync();
}
static Key *
match_keys(Key *k, ulong mod, KeyCode keycode, Bool seq) {
match_keys(Key *k, ulong mod, KeyCode keycode, bool seq) {
Key *ret = nil, *next;
for(next = k->tnext; k; (k=next) && (next=k->tnext)) {
@ -181,12 +189,12 @@ kpress_seq(XWindow w, Key *done) {
next_keystroke(&mod, &key);
found = match_keys(done, mod, key, True);
if((done->mod == mod) && (done->key == key))
emulate_key_press(mod, key); /* double key */
fake_keypress(mod, key); /* double key */
else {
if(!found)
XBell(display, 0);
else if(!found->tnext && !found->next)
write_event("Key %s\n", found->name);
event("Key %s\n", found->name);
else
kpress_seq(w, found);
}
@ -202,13 +210,13 @@ kpress(XWindow w, ulong mod, KeyCode keycode) {
if(!found) /* grabbed but not found */
XBell(display, 0);
else if(!found->tnext && !found->next)
write_event("Key %s\n", found->name);
event("Key %s\n", found->name);
else {
XGrabKeyboard(display, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
flushevents(FocusChangeMask, True);
kpress_seq(w, found);
XUngrabKeyboard(display, CurrentTime);
XSync(display, False);
sync();
}
}
@ -220,7 +228,7 @@ update_keys(void) {
init_lock_keys();
while((k = key)) {
key = key->lnext;
ungrab_key(k);
ungrabkey(k);
while((n = k)) {
k = k->next;
free(n);
@ -229,8 +237,8 @@ update_keys(void) {
for(l = p = def.keys; p && *p;) {
if(*p == '\n') {
*p = 0;
if((k = get_key(l)))
grab_key(k);
if((k = getkey(l)))
grabkey(k);
*p = '\n';
l = ++p;
}
@ -238,8 +246,8 @@ update_keys(void) {
p++;
}
if(l < p && strlen(l)) {
if((k = get_key(l)))
grab_key(k);
if((k = getkey(l)))
grabkey(k);
}
XSync(display, False);
sync();
}

View File

@ -2,16 +2,15 @@
* Copyright ©2006-2007 Kris Maglione <fbsdaemon@gmail.com>
* See LICENSE file for license details.
*/
#define EXTERN
#include "dat.h"
#include <X11/Xproto.h>
#include <X11/cursorfont.h>
#include <errno.h>
#include <fcntl.h>
#include <locale.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
@ -22,7 +21,7 @@ static const char
static int (*xlib_errorhandler) (Display*, XErrorEvent*);
static char *address, *ns_path;
static Bool check_other_wm;
static int check_other_wm;
static struct sigaction sa;
static struct passwd *passwd;
static int sleeperfd, sock, exitsignal;
@ -49,17 +48,19 @@ scan_wins(void) {
for(i = 0; i < num; i++) {
if(!XGetWindowAttributes(display, wins[i], &wa))
continue;
/* Skip transients. */
if(wa.override_redirect || XGetTransientForHint(display, wins[i], &d1))
continue;
if(wa.map_state == IsViewable)
create_client(wins[i], &wa);
client_create(wins[i], &wa);
}
/* Manage transients. */
for(i = 0; i < num; i++) {
if(!XGetWindowAttributes(display, wins[i], &wa))
continue;
if((XGetTransientForHint(display, wins[i], &d1))
&& (wa.map_state == IsViewable))
create_client(wins[i], &wa);
client_create(wins[i], &wa);
}
}
if(wins)
@ -88,20 +89,21 @@ ns_display(void) {
static void
rmkdir(char *path, int mode) {
char *p, *q;
char *p;
int ret;
char c;
q = path + strlen(ns_path);
for(p = &path[1]; p <= q; p++) {
for(p = path+1; ; p++) {
c = *p;
if((c == '/') || (c == '\0')) {
*p = '\0';
ret = mkdir(path, mode);
if((ret == -1) && (errno != EEXIST))
fatal("Can't create ns_path '%s': %r", path);
fatal("Can't create path '%s': %r", path);
*p = c;
}
if(c == '\0')
break;
}
}
@ -121,7 +123,7 @@ init_ns(void) {
else
ns_path = ns_display();
if((ns_path[0] != '/') || (strlen(ns_path) == 0))
if(ns_path[0] != '/' || ns_path[0] == '\0')
fatal("Bad ns_path");
rmkdir(ns_path, 0700);
@ -138,22 +140,13 @@ static void
init_environment(void) {
init_ns();
if(address == nil) {
address = emalloc(strlen(ns_path) + strlen("unix!/wmii") + 1);
sprint(address, "unix!%s/wmii", ns_path);
}
if(address == nil)
address = smprint("unix!%s/wmii", ns_path);
setenv("WMII_NS_DIR", ns_path, True);
setenv("WMII_ADDRESS", address, True);
}
static void
init_atoms(void) {
Atom net[] = { xatom("_NET_SUPPORTED"), xatom("_NET_WM_NAME") };
changeprop_long(&scr.root, "_NET_SUPPORTED", "ATOM", (long*)net, nelem(net));
}
static void
create_cursor(int ident, uint shape) {
cursor[ident] = XCreateFontCursor(display, shape);
@ -192,40 +185,17 @@ init_cursors(void) {
static void
init_screen(WMScreen *screen) {
XWindow w;
int ret;
unsigned mask;
XGCValues gcv;
gcv.subwindow_mode = IncludeInferiors;
gcv.function = GXxor;
gcv.foreground = def.normcolor.bg;
gcv.plane_mask = AllPlanes;
gcv.graphics_exposures = False;
xor.type = WImage;
xor.image = scr.root.w;
xor.gc = XCreateGC(display, scr.root.w,
GCForeground
| GCGraphicsExposures
| GCFunction
| GCSubwindowMode
| GCPlaneMask,
&gcv);
screen->r = scr.rect;
def.snap = Dy(scr.rect) / 63;
sel_screen = XQueryPointer(display, scr.root.w,
&w, &w,
&ret, &ret, &ret, &ret,
&mask);
sel_screen = pointerscreen();
}
static void
cleanup(void) {
while(client)
destroy_client(client);
client_destroy(client);
ixp_server_close(&srv);
close(sleeperfd);
}
@ -240,6 +210,7 @@ struct {
{ X_PolySegment, BadDrawable },
{ X_ConfigureWindow, BadMatch },
{ X_GrabKey, BadAccess },
{ X_GetAtomName, BadAtom },
};
/*
@ -250,9 +221,9 @@ struct {
*/
static int
errorhandler(Display *dpy, XErrorEvent *error) {
static Bool dead;
static int dead;
int i;
USED(dpy);
if(check_other_wm)
@ -266,7 +237,7 @@ errorhandler(Display *dpy, XErrorEvent *error) {
fprint(2, "%s: fatal error: Xrequest code=%d, Xerror code=%d\n",
argv0, error->request_code, error->error_code);
/* Try to cleanup, but only try once, in case we're called again */
/* Try to cleanup, but only try once, in case we're called recursively. */
if(!dead++)
cleanup();
return xlib_errorhandler(display, error); /* calls exit() */
@ -288,47 +259,58 @@ cleanup_handler(int signal) {
}
}
static void
closeexec(int fd) {
fcntl(fd, F_SETFL, FD_CLOEXEC);
}
static int
doublefork(void) {
pid_t pid;
int status;
switch(pid=fork()) {
case -1:
fatal("Can't fork(): %r");
case 0:
switch(pid=fork()) {
case -1:
fatal("Can't fork(): %r");
case 0:
return 0;
default:
exit(0);
}
default:
waitpid(pid, &status, 0);
return pid;
}
return -1; /* not reached */
}
static void
init_traps(void) {
char buf[1];
pid_t pid;
int fd[2], status;
int fd[2];
if(pipe(fd) != 0)
fatal("Can't pipe(): %r");
/* Double fork hack */
switch(pid = fork()) {
case -1:
fatal("Can't fork(): %r");
break; /* not reached */
case 0:
switch(fork()) {
case -1:
fatal("Can't fork(): %r");
break; /* not reached */
case 0:
close(fd[1]);
close(ConnectionNumber(display));
setsid();
if(doublefork() == 0) {
close(fd[1]);
close(ConnectionNumber(display));
setsid();
display = XOpenDisplay(0);
if(!display)
fatal("Can't open display");
display = XOpenDisplay(0);
if(!display)
fatal("Can't open display");
/* Wait for parent to exit */
read(fd[0], buf, 1);
/* Wait for parent to exit */
read(fd[0], buf, 1);
XSetInputFocus(display, PointerRoot, RevertToPointerRoot, CurrentTime);
XCloseDisplay(display);
exit(0);
default:
exit(0);
break;
}
default:
waitpid(pid, &status, 0);
break;
setfocus(pointerwin, RevertToPointerRoot);
XCloseDisplay(display);
exit(0);
}
close(fd[0]);
@ -340,50 +322,28 @@ init_traps(void) {
sigaction(SIGTERM, &sa, nil);
sigaction(SIGQUIT, &sa, nil);
sigaction(SIGHUP, &sa, nil);
sigaction(SIGUSR1, &sa, nil);
sigaction(SIGUSR2, &sa, nil);
}
static void
spawn_command(const char *cmd) {
char *shell, *p;
pid_t pid;
int status;
/* Double fork hack */
switch(pid = fork()) {
case -1:
fatal("Can't fork: %r");
break; /* Not reached */
case 0:
switch(fork()) {
case -1:
fatal("Can't fork: %r");
break; /* Not reached */
case 0:
if(setsid() == -1)
fatal("Can't setsid: %r");
close(sock);
close(ConnectionNumber(display));
if(doublefork() == 0) {
if(setsid() == -1)
fatal("Can't setsid: %r");
shell = passwd->pw_shell;
if(shell[0] != '/')
fatal("Shell is not an absolute path: %s", shell);
shell = passwd->pw_shell;
if(shell[0] != '/')
fatal("Shell is not an absolute path: %s", shell);
/* Run through the user's shell as a login shell */
p = malloc((strlen(shell) + 2));
sprint(p, "-%s", strrchr(shell, '/') + 1);
/* Run through the user's shell as a login shell */
p = smprint("-%s", strrchr(shell, '/') + 1);
execl(shell, p, "-c", cmd, nil);
fatal("Can't exec '%s': %r", cmd);
break; /* Not reached */
default:
exit(0);
break; /* Not reached */
}
default:
waitpid(pid, &status, 0);
/* if(status != 0)
exit(1); */
break;
execl(shell, p, "-c", cmd, nil);
fatal("Can't exec '%s': %r", cmd);
/* Not reached */
}
}
@ -417,9 +377,6 @@ main(int argc, char *argv[]) {
case 'v':
print("%s", version);
exit(0);
case 'V':
verbose = True;
break;
case 'a':
address = EARGF(usage());
break;
@ -438,16 +395,17 @@ main(int argc, char *argv[]) {
starting = True;
initdisplay();
closeexec(ConnectionNumber(display));
xlib_errorhandler = XSetErrorHandler(errorhandler);
check_other_wm = True;
check_other_wm = true;
XSelectInput(display, scr.root.w,
SubstructureRedirectMask
| EnterWindowMask);
XSync(display, False);
sync();
check_other_wm = False;
check_other_wm = false;
passwd = getpwuid(getuid());
user = estrdup(passwd->pw_name);
@ -457,14 +415,15 @@ main(int argc, char *argv[]) {
sock = ixp_announce(address);
if(sock < 0)
fatal("Can't create socket '%s': %r", address);
closeexec(sock);
if(wmiirc)
spawn_command(wmiirc);
init_traps();
init_atoms();
init_cursors();
init_lock_keys();
ewmh_init();
srv.preselect = check_preselect;
ixp_listen(&srv, sock, &p9srv, serve_9pcon, nil);
@ -499,20 +458,21 @@ main(int argc, char *argv[]) {
setwinattr(&scr.root, &wa,
CWEventMask
| CWCursor);
initbar(s);
bar_init(s);
}
screen->focus = nil;
setfocus(screen->barwin, RevertToParent);
scan_wins();
starting = False;
starting = false;
select_view("nil");
update_views();
write_event("FocusTag %s\n", screen->sel->name);
view_select("nil");
view_update_all();
ewmh_updateviews();
event("FocusTag %s\n", screen->sel->name);
check_x_event(nil);
i = ixp_serverloop(&srv);
if(i)
fprint(2, "%s: error: %r\n", argv0);

View File

@ -1,8 +1,6 @@
/* Written by Kris Maglione */
/* Public domain */
#include "dat.h"
#include <stdlib.h>
#include <string.h>
#include "fns.h"
/* Edit s/^([a-zA-Z].*)\n([a-z].*) {/\1 \2;/g x/^([^a-zA-Z]|static|$)/-+d s/ (\*map|val|*str)//g */
@ -23,7 +21,7 @@ hash(const char *str) {
}
static void
insert(MapEnt **e, ulong val, char *key) {
insert(MapEnt **e, ulong val, const char *key) {
MapEnt *te;
te = emallocz(sizeof *te);
@ -34,7 +32,7 @@ insert(MapEnt **e, ulong val, char *key) {
}
static MapEnt**
mapgetp(Map *map, ulong val, int create) {
map_getp(Map *map, ulong val, int create) {
MapEnt **e;
e = &map->bucket[val%map->nhash];
@ -50,13 +48,13 @@ mapgetp(Map *map, ulong val, int create) {
}
static MapEnt**
hashgetp(Map *map, char *str, int create) {
hash_getp(Map *map, const char *str, int create) {
MapEnt **e;
ulong h;
int cmp;
h = hash(str);
e = mapgetp(map, h, create);
e = map_getp(map, h, create);
if(*e && (*e)->key == nil)
(*e)->key = str;
else {
@ -72,28 +70,28 @@ hashgetp(Map *map, char *str, int create) {
}
MapEnt*
mapget(Map *map, ulong val, int create) {
map_get(Map *map, ulong val, int create) {
MapEnt **e;
e = mapgetp(map, val, create);
e = map_getp(map, val, create);
return *e;
}
MapEnt*
hashget(Map *map, char *str, int create) {
hash_get(Map *map, const char *str, int create) {
MapEnt **e;
e = hashgetp(map, str, create);
e = hash_getp(map, str, create);
return *e;
}
void*
maprm(Map *map, ulong val) {
map_rm(Map *map, ulong val) {
MapEnt **e, *te;
void *ret;
ret = nil;
e = mapgetp(map, val, 0);
e = map_getp(map, val, 0);
if(*e) {
te = *e;
ret = te->val;
@ -104,12 +102,12 @@ maprm(Map *map, ulong val) {
}
void*
hashrm(Map *map, char *str) {
hash_rm(Map *map, const char *str) {
MapEnt **e, *te;
void *ret;
ret = nil;
e = hashgetp(map, str, 0);
e = hash_getp(map, str, 0);
if(*e) {
te = *e;
ret = te->val;

View File

@ -4,11 +4,12 @@
#include "dat.h"
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fns.h"
static char* msg_debug(IxpMsg*);
static char* msg_selectframe(Frame*, IxpMsg*, int);
static char* msg_sendframe(Frame*, int, bool);
static char
Ebadcmd[] = "bad command",
Ebadvalue[] = "bad value",
@ -21,6 +22,7 @@ enum {
LBORDER,
LCLIENT,
LCOLMODE,
LDEBUG,
LDOWN,
LEXEC,
LFOCUSCOLORS,
@ -48,6 +50,7 @@ char *symtab[] = {
"border",
"client",
"colmode",
"debug",
"down",
"exec",
"focuscolors",
@ -70,23 +73,30 @@ char *symtab[] = {
"~",
};
char *debugtab[] = {
"event",
"ewmh",
"focus",
"generic",
};
/* Edit ,y/^[a-zA-Z].*\n.* {\n/d
* Edit s/^([a-zA-Z].*)\n(.*) {\n/\1 \2;\n/
* Edit ,x/^static.*\n/d
*/
static int
getsym(char *s) {
_bsearch(char *s, char **tab, int ntab) {
int i, n, m, cmp;
if(s == nil)
return -1;
n = nelem(symtab);
n = ntab;
i = 0;
while(n) {
m = n/2;
cmp = strcmp(s, symtab[i+m]);
cmp = strcmp(s, tab[i+m]);
if(cmp == 0)
return i+m;
if(cmp < 0 || m == 0)
@ -99,9 +109,19 @@ getsym(char *s) {
return -1;
}
static int
getsym(char *s) {
return _bsearch(s, symtab, nelem(symtab));
}
static int
getdebug(char *s) {
return _bsearch(s, debugtab, nelem(debugtab));
}
static int
gettoggle(IxpMsg *m) {
switch(getsym(getword(m))) {
switch(getsym(msg_getword(m))) {
case LON:
return On;
case LOFF:
@ -119,7 +139,7 @@ eatrunes(IxpMsg *m, int (*p)(Rune), int val) {
int n;
while(m->pos < m->end) {
n = chartorune(&r, (char*)m->pos);
n = chartorune(&r, m->pos);
if(p(r) != val)
break;
m->pos += n;
@ -128,44 +148,46 @@ eatrunes(IxpMsg *m, int (*p)(Rune), int val) {
m->pos = m->end;
}
char *
getword(IxpMsg *m) {
char*
msg_getword(IxpMsg *m) {
char *ret;
Rune r;
int n;
eatrunes(m, isspacerune, 1);
ret = (char*)m->pos;
ret = m->pos;
eatrunes(m, isspacerune, 0);
n = chartorune(&r, (char*)m->pos);
n = chartorune(&r, m->pos);
*m->pos = '\0';
m->pos += n;
eatrunes(m, isspacerune, 1);
if(ret == (char*)m->end)
if(ret == m->end)
return nil;
return ret;
}
#define strbcmp(str, const) (strncmp((str), (const), sizeof(const)-1))
static int
getbase(char **s) {
char *p;
getbase(const char **s) {
const char *p;
p = *s;
if(!strbcmp(p, "0x")) {
*s += 2;
return 16;
}
if(isdigit(p[0]) && p[1] == 'r') {
*s += 2;
return p[0] - '0';
if(isdigit(p[0])) {
if(p[1] == 'r') {
*s += 2;
return p[0] - '0';
}
if(isdigit(p[1]) && p[2] == 'r') {
*s += 3;
return 10*(p[0]-'0') + (p[1]-'0');
}
}
if(isdigit(p[0]) && isdigit(p[1]) && p[2] == 'r') {
*s += 3;
return 10*(p[0]-'0') + (p[1]-'0');
}
if(!strbcmp(p, "0")) {
if(p[0] == '0') {
*s += 1;
return 8;
}
@ -173,8 +195,9 @@ getbase(char **s) {
}
int
getlong(char *s, long *ret) {
char *end, *rend;
getlong(const char *s, long *ret) {
const char *end;
char *rend;
int base;
end = s+strlen(s);
@ -185,8 +208,9 @@ getlong(char *s, long *ret) {
}
int
getulong(char *s, ulong *ret) {
char *end, *rend;
getulong(const char *s, ulong *ret) {
const char *end;
char *rend;
int base;
end = s+strlen(s);
@ -196,7 +220,7 @@ getulong(char *s, ulong *ret) {
return (end == rend);
}
static Client *
static Client*
strclient(View *v, char *s) {
ulong id;
@ -208,8 +232,8 @@ strclient(View *v, char *s) {
return nil;
}
Area *
strarea(View *v, char *s) {
Area*
strarea(View *v, const char *s) {
Area *a;
long i;
@ -220,10 +244,10 @@ strarea(View *v, char *s) {
if(!getlong(s, &i) || i == 0)
return nil;
if(i > 0)
for(a = v->area; a; a = a->next) {
if(i > 0) {
for(a = v->area; a; a = a->next)
if(i-- == 0) break;
}
}
else {
for(a = v->area; a->next; a = a->next)
;
@ -235,80 +259,36 @@ strarea(View *v, char *s) {
return a;
}
char *
message_view(View *v, IxpMsg *m) {
Area *a;
char*
message_client(Client *c, IxpMsg *m) {
char *s;
int i;
s = getword(m);
s = msg_getword(m);
switch(getsym(s)) {
case LSEND:
return send_client(v, m, 0);
case LSWAP:
return send_client(v, m, 1);
case LSELECT:
return select_area(v->sel, m);
case LCOLMODE:
s = getword(m);
if((a = strarea(v, s)) == nil || a->floating)
return Ebadvalue;
s = getword(m);
if((i = str2colmode(s)) == -1)
return Ebadvalue;
a->mode = i;
arrange_column(a, True);
restack_view(v);
if(v == screen->sel)
focus_view(screen, v);
draw_frames();
return nil;
case LFULLSCREEN:
i = gettoggle(m);
if(i == -1)
return Ebadusage;
fullscreen(c, i);
break;
case LKILL:
client_kill(c);
break;
case LURGENT:
i = gettoggle(m);
if(i == -1)
return Ebadusage;
client_seturgent(c, i, True);
break;
default:
return Ebadcmd;
}
/* not reached */
}
char *
parse_colors(IxpMsg *m, CTuple *col) {
static char Ebad[] = "bad color string";
Rune r;
char c, *p;
int i, j;
/* '#%6x #%6x #%6x' */
p = (char*)m->pos;
for(i = 0; i < 3 && p < (char*)m->end; i++) {
if(*p++ != '#')
return Ebad;
for(j = 0; j < 6 && p < (char*)m->end; j++)
if(!isxdigit(*p++))
return Ebad;
chartorune(&r, p);
if(i < 2) {
if(r != ' ')
return Ebad;
p++;
}else if(!isspacerune(r) && *p != '\0')
return Ebad;
}
c = *p;
*p = '\0';
loadcolor(col, (char*)m->pos);
*p = c;
m->pos = (uchar*)p;
eatrunes(m, isspacerune, 1);
return nil;
}
char *
char*
message_root(void *p, IxpMsg *m) {
Font *fn;
char *s, *ret;
@ -316,48 +296,38 @@ message_root(void *p, IxpMsg *m) {
USED(p);
ret = nil;
s = getword(m);
s = msg_getword(m);
switch(getsym(s)) {
case LQUIT:
srv.running = 0;
case LBORDER:
if(!getulong(msg_getword(m), &n))
return Ebadvalue;
def.border = n;
view_focus(screen, screen->sel);
break;
case LDEBUG:
ret = msg_debug(m);
break;
case LEXEC:
execstr = smprint("exec %s", (char*)m->pos);
execstr = smprint("exec %s", m->pos);
srv.running = 0;
break;
case LVIEW:
select_view((char*)m->pos);
break;
case LSELCOLORS:
fprint(2, "%s: warning: selcolors have been removed\n", argv0);
return Ebadcmd;
case LFOCUSCOLORS:
ret = parse_colors(m, &def.focuscolor);
focus_view(screen, screen->sel);
break;
case LNORMCOLORS:
ret = parse_colors(m, &def.normcolor);
focus_view(screen, screen->sel);
ret = msg_parsecolors(m, &def.focuscolor);
view_focus(screen, screen->sel);
break;
case LFONT:
fn = loadfont((char*)m->pos);
fn = loadfont(m->pos);
if(fn) {
freefont(def.font);
def.font = fn;
resize_bar(screen);
bar_resize(screen);
}else
ret = "can't load font";
focus_view(screen, screen->sel);
break;
case LBORDER:
if(!getulong(getword(m), &n))
return Ebadvalue;
def.border = n;
focus_view(screen, screen->sel);
view_focus(screen, screen->sel);
break;
case LGRABMOD:
s = getword(m);
s = msg_getword(m);
n = str2modmask(s);
if((n & (Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) == 0)
@ -366,97 +336,276 @@ message_root(void *p, IxpMsg *m) {
utflcpy(def.grabmod, s, sizeof(def.grabmod));
def.mod = n;
break;
case LNORMCOLORS:
ret = msg_parsecolors(m, &def.normcolor);
view_focus(screen, screen->sel);
break;
case LSELCOLORS:
fprint(2, "%s: warning: selcolors have been removed\n", argv0);
return Ebadcmd;
case LVIEW:
view_select(m->pos);
break;
case LQUIT:
srv.running = 0;
break;
default:
return Ebadcmd;
}
return ret;
}
char *
read_root_ctl(void) {
char *b, *e;
b = buffer;
e = b + sizeof(buffer) - 1;
b = seprint(b, e, "view %s\n", screen->sel->name);
b = seprint(b, e, "focuscolors %s\n", def.focuscolor.colstr);
b = seprint(b, e, "normcolors %s\n", def.normcolor.colstr);
b = seprint(b, e, "font %s\n", def.font->name);
b = seprint(b, e, "grabmod %s\n", def.grabmod);
b = seprint(b, e, "border %d\n", def.border);
USED(b);
return buffer;
}
char *
message_client(Client *c, IxpMsg *m) {
char*
message_view(View *v, IxpMsg *m) {
Area *a;
char *s;
int i;
s = getword(m);
s = msg_getword(m);
switch(getsym(s)) {
case LKILL:
kill_client(c);
break;
case LURGENT:
i = gettoggle(m);
case LCOLMODE:
s = msg_getword(m);
a = strarea(v, s);
if(a == nil || a->floating)
return Ebadvalue;
s = msg_getword(m);
i = str2colmode(s);
if(i == -1)
return Ebadusage;
set_urgent(c, i, True);
break;
case LFULLSCREEN:
i = gettoggle(m);
if(i == -1)
return Ebadusage;
fullscreen(c, i);
break;
return Ebadvalue;
a->mode = i;
column_arrange(a, True);
view_restack(v);
if(v == screen->sel)
view_focus(screen, v);
frame_draw_all();
return nil;
case LSELECT:
return msg_selectarea(v->sel, m);
case LSEND:
return msg_sendclient(v, m, 0);
case LSWAP:
return msg_sendclient(v, m, 1);
default:
return Ebadcmd;
}
/* not reached */
}
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]);
}
}
char*
root_readctl(void) {
bufclear();
bufprint("view %s\n", screen->sel->name);
bufprint("focuscolors %s\n", def.focuscolor.colstr);
bufprint("normcolors %s\n", def.normcolor.colstr);
bufprint("font %s\n", def.font->name);
bufprint("grabmod %s\n", def.grabmod);
bufprint("border %d\n", def.border);
if(debug) {
bufprint("debug ");
printdebug();
bufprint("\n");
}
return buffer;
}
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') {
opt = smprint("Bad debug options: %s", buffer+2);
utfecpy(buffer, buffer+sizeof(buffer), opt);
free(opt);
return buffer;
}
return nil;
}
char*
msg_parsecolors(IxpMsg *m, CTuple *col) {
static char Ebad[] = "bad color string";
Rune r;
char c, *p;
int i, j;
/* '#%6x #%6x #%6x' */
p = m->pos;
for(i = 0; i < 3 && p < m->end; i++) {
if(*p++ != '#')
return Ebad;
for(j = 0; j < 6; j++)
if(p >= m->end || !isxdigit(*p++))
return Ebad;
chartorune(&r, p);
if(i < 2) {
if(r != ' ')
return Ebad;
p++;
}else if(*p != '\0' && !isspacerune(r))
return Ebad;
}
c = *p;
*p = '\0';
loadcolor(col, m->pos);
*p = c;
m->pos = p;
eatrunes(m, isspacerune, 1);
return nil;
}
char*
msg_selectarea(Area *a, IxpMsg *m) {
Frame *f;
Area *ap;
View *v;
char *s;
ulong i;
int sym;
v = a->view;
s = msg_getword(m);
sym = getsym(s);
switch(sym) {
case LTOGGLE:
if(!a->floating)
ap = v->area;
else if(v->revert && v->revert != a)
ap = v->revert;
else
ap = v->area->next;
break;
case LUP:
case LDOWN:
case LCLIENT:
return msg_selectframe(a->sel, m, sym);
case LLEFT:
if(a->floating)
return Ebadvalue;
for(ap=v->area->next; ap->next; ap=ap->next)
if(ap->next == a) break;
break;
case LRIGHT:
if(a->floating)
return Ebadvalue;
ap = a->next;
if(ap == nil)
ap = v->area->next;
break;
case LTILDE:
ap = v->area;
break;
default:
if(!strcmp(s, "sel"))
ap = v->sel;
else {
if(!getulong(s, &i) || i == 0)
return Ebadvalue;
for(ap=v->area->next; ap; ap=ap->next)
if(--i == 0) break;
if(i != 0)
return Ebadvalue;
}
if((s = msg_getword(m))) {
if(!getulong(s, &i))
return Ebadvalue;
for(f = ap->frame; f; f = f->anext)
if(--i == 0) break;
if(i != 0)
return Ebadvalue;
frame_focus(f);
return nil;
}
}
area_focus(ap);
return nil;
}
static char*
send_frame(Frame *f, int sym, Bool swap) {
msg_selectframe(Frame *f, IxpMsg *m, int sym) {
Frame *fp;
Client *c;
Area *a;
char *s;
ulong i;
if(!f)
return Ebadvalue;
a = f->area;
SET(fp);
switch(sym) {
case LUP:
fp = f->aprev;
if(!fp)
return Ebadvalue;
fp = fp->aprev;
for(fp = a->frame; fp->anext; fp = fp->anext)
if(fp->anext == f) break;
break;
case LDOWN:
fp = f->anext;
if(!fp)
return Ebadvalue;
if(fp == nil)
fp = a->frame;
break;
case LCLIENT:
s = msg_getword(m);
if(s == nil || !getulong(s, &i))
return "usage: select client <client>";
c = win2client(i);
if(c == nil)
return "unknown client";
fp = client_viewframe(c, f->view);
break;
default:
assert(!"can't get here");
die("can't get here");
}
if(swap) {
if(!fp)
return Ebadvalue;
swap_frames(f, fp);
}else {
remove_frame(f);
insert_frame(fp, f);
}
if(fp == nil)
return "invalid selection";
arrange_view(f->view);
flushevents(EnterWindowMask, False);
focus_frame(f, True);
update_views();
frame_focus(fp);
frame_to_top(fp);
if(f->view == screen->sel)
view_restack(f->view);
return nil;
}
char *
send_client(View *v, IxpMsg *m, Bool swap) {
char*
msg_sendclient(View *v, IxpMsg *m, bool swap) {
Area *to, *a;
Frame *f;
Client *c;
@ -464,26 +613,26 @@ send_client(View *v, IxpMsg *m, Bool swap) {
ulong i;
int sym;
s = getword(m);
s = msg_getword(m);
c = strclient(v, s);
if(c == nil)
return Ebadvalue;
f = view_clientframe(v, c);
f = client_viewframe(c, v);
if(f == nil)
return Ebadvalue;
a = f->area;
to = nil;
s = getword(m);
s = msg_getword(m);
sym = getsym(s);
switch(sym) {
case LUP:
case LDOWN:
return send_frame(f, sym, swap);
return msg_sendframe(f, sym, swap);
case LLEFT:
if(a->floating)
return Ebadvalue;
@ -516,136 +665,60 @@ send_client(View *v, IxpMsg *m, Bool swap) {
}
if(!to && !swap && (f->anext || f != f->area->frame))
to = new_column(v, a, 0);
to = column_new(v, a, 0);
if(!to)
return Ebadvalue;
if(!swap)
send_to_area(to, f);
area_moveto(to, f);
else if(to->sel)
swap_frames(f, to->sel);
frame_swap(f, to->sel);
else
return Ebadvalue;
flushevents(EnterWindowMask, False);
focus_frame(f, True);
arrange_view(v);
update_views();
frame_focus(f);
view_arrange(v);
view_update_all();
return nil;
}
static char*
select_frame(Frame *f, IxpMsg *m, int sym) {
msg_sendframe(Frame *f, int sym, bool swap) {
Frame *fp;
Client *c;
Area *a;
char *s;
ulong i;
if(!f)
return Ebadvalue;
a = f->area;
SET(fp);
switch(sym) {
case LUP:
for(fp = a->frame; fp->anext; fp = fp->anext)
if(fp->anext == f) break;
fp = f->aprev;
if(!fp)
return Ebadvalue;
fp = fp->aprev;
break;
case LDOWN:
fp = f->anext;
if(fp == nil)
fp = a->frame;
break;
case LCLIENT:
s = getword(m);
if(s == nil || !getulong(s, &i))
return "usage: select client <client>";
c = win2client(i);
if(c == nil)
return "unknown client";
fp = view_clientframe(f->view, c);
if(!fp)
return Ebadvalue;
break;
default:
assert(!"can't get here");
die("can't get here");
}
if(fp == nil)
return "invalid selection";
if(swap) {
if(!fp)
return Ebadvalue;
frame_swap(f, fp);
}else {
frame_remove(f);
frame_insert(fp, f);
}
focus_frame(fp, False);
frame_to_top(fp);
if(f->view == screen->sel)
restack_view(f->view);
view_arrange(f->view);
flushevents(EnterWindowMask, False);
frame_focus(f);
view_update_all();
return nil;
}
char*
select_area(Area *a, IxpMsg *m) {
Frame *f;
Area *ap;
View *v;
char *s;
ulong i;
int sym;
v = a->view;
s = getword(m);
sym = getsym(s);
switch(sym) {
case LTOGGLE:
if(!a->floating)
ap = v->area;
else if(v->revert && v->revert != a)
ap = v->revert;
else
ap = v->area->next;
break;
case LUP:
case LDOWN:
case LCLIENT:
return select_frame(a->sel, m, sym);
case LLEFT:
if(a->floating)
return Ebadvalue;
for(ap=v->area->next; ap->next; ap=ap->next)
if(ap->next == a) break;
break;
case LRIGHT:
if(a->floating)
return Ebadvalue;
ap = a->next;
if(ap == nil)
ap = v->area->next;
break;
case LTILDE:
ap = v->area;
break;
default:
if(!strcmp(s, "sel"))
ap = v->sel;
else {
if(!getulong(s, &i) || i == 0)
return Ebadvalue;
for(ap=v->area->next; ap; ap=ap->next)
if(--i == 0) break;
if(i != 0)
return Ebadvalue;
}
if((s = getword(m))) {
if(!getulong(s, &i))
return Ebadvalue;
for(f = ap->frame; f; f = f->anext)
if(--i == 0) break;
if(i != 0)
return Ebadvalue;
focus_frame(f, True);
return nil;
}
}
focus_area(ap);
return nil;
}

View File

@ -3,9 +3,6 @@
*/
#include "dat.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "fns.h"
enum {
@ -50,9 +47,9 @@ framerect(Framewin *f) {
/* Keep onscreen */
p = ZP;
p.x -= min(r.min.x, 0);
p.x -= max(r.max.x - screen->r.max.x, 0);
p.y -= max(r.max.y - screen->brect.min.y - Dy(r)/2, 0);
p.x -= min(0, r.min.x);
p.x -= max(0, r.max.x - screen->r.max.x);
p.y -= max(0, r.max.y - screen->brect.min.y - Dy(r)/2);
return rectaddpt(r, p);
}
@ -238,7 +235,7 @@ do_managed_move(Client *c) {
Point pt, pt2;
int y;
focus(c, False);
focus(c, false);
f = c->sel;
pt = querypointer(&scr.root);
@ -254,7 +251,7 @@ do_managed_move(Client *c) {
mapwin(cwin);
horiz:
XUngrabPointer(display, CurrentTime);
ungrabpointer();
if(!grabpointer(&scr.root, nil, cursor[CurIcon], MouseMask))
goto done;
warppointer(pt);
@ -276,9 +273,10 @@ horiz:
case ButtonRelease:
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;
resize_frame(f->anext, f->anext->r);
frame_resize(f->anext, f->anext->r);
}
else if(f->aprev) {
if(fw->fp == f->aprev->aprev) {
@ -286,16 +284,16 @@ horiz:
f->aprev->r = f->r;
}else
f->aprev->r.max.y = f->r.max.y;
resize_frame(f->aprev, f->aprev->r);
frame_resize(f->aprev, f->aprev->r);
}
remove_frame(f);
frame_remove(f);
f->area = fw->ra;
insert_frame(fw->fp, f);
frame_insert(fw->fp, f);
if(f->aprev) {
f->aprev->r.max.y = fw->fr.min.y;
resize_frame(f->aprev, f->aprev->r);
frame_resize(f->aprev, f->aprev->r);
}
else
fw->fr.min.y = f->area->r.min.y;
@ -303,9 +301,9 @@ horiz:
fw->fr.max.y = f->anext->r.min.y;
else
fw->fr.max.y = f->area->r.max.y;
resize_frame(f, fw->fr);
frame_resize(f, fw->fr);
arrange_view(f->view);
view_arrange(f->view);
goto done;
}
break;
@ -319,7 +317,7 @@ horiz:
}
vert:
y = pt.y;
XUngrabPointer(display, CurrentTime);
ungrabpointer();
if(!grabpointer(&scr.root, cwin, cursor[CurIcon], MouseMask))
goto done;
hplace(fw, pt);
@ -341,8 +339,8 @@ vert:
switch(ev.xbutton.button) {
case 1:
if(fw->ra) {
fw->ra = new_column(f->view, fw->ra, 0);
send_to_area(fw->ra, f);
fw->ra = column_new(f->view, fw->ra, 0);
area_moveto(fw->ra, f);
}
goto done;
case 2:
@ -353,7 +351,7 @@ vert:
}
}
done:
XUngrabPointer(display, CurrentTime);
ungrabpointer();
framedestroy(fw);
destroywindow(cwin);
@ -363,7 +361,7 @@ done:
warppointer(pt);
}
static Window *
static Window*
gethsep(Rectangle r) {
Window *w;
WinAttr wa;
@ -471,7 +469,7 @@ mouse_resizecolframe(Frame *f, Align align) {
r.min.y = ((align&SOUTH) ? pt.y : pt.y-1);
r.max.y = r.min.y+2;
setdiv(d, pt.x);
div_set(d, pt.x);
reshapewin(hwin, r);
break;
case ButtonRelease:
@ -484,8 +482,9 @@ mouse_resizecolframe(Frame *f, Align align) {
r.min.y = pt.y;
else
r.max.y = pt.y;
resize_colframe(f, &r);
column_resizeframe(f, &r);
/* XXX: Magic number... */
if(align&WEST)
pt.x = f->r.min.x + 4;
else
@ -499,7 +498,7 @@ mouse_resizecolframe(Frame *f, Align align) {
}
}
done:
XUngrabPointer(display, CurrentTime);
ungrabpointer();
destroywindow(cwin);
destroywindow(hwin);
}
@ -549,20 +548,20 @@ mouse_resizecol(Divide *d) {
break;
case MotionNotify:
pt.x = ev.xmotion.x_root;
setdiv(d, pt.x);
div_set(d, pt.x);
break;
case ButtonRelease:
resize_column(a, pt.x - a->r.min.x);
column_resize(a, pt.x - a->r.min.x);
goto done;
}
}
done:
XUngrabPointer(display, CurrentTime);
ungrabpointer();
destroywindow(cwin);
}
static void
rect_morph_xy(Rectangle *r, Point d, Align *mask) {
rect_morph(Rectangle *r, Point d, Align *mask) {
int n;
if(*mask & NORTH)
@ -589,38 +588,43 @@ rect_morph_xy(Rectangle *r, Point d, Align *mask) {
}
static int
snap_line(Rectangle *rects, int nrect, int d, int horiz, Rectangle *r, int x, int y) {
snap_hline(Rectangle *rects, int nrect, int dy, Rectangle *r, int y) {
Rectangle *rp;
int i, tx, ty;
int i, ty;
if(horiz) {
for(i=0; i < nrect; i++) {
rp = &rects[i];
if((rp->min.x <= r->max.x) && (rp->max.x >= r->min.x)) {
ty = rp->min.y;
if(abs(ty - y) <= abs(d))
d = ty - y;
for(i=0; i < nrect; i++) {
rp = &rects[i];
if((rp->min.x <= r->max.x) && (rp->max.x >= r->min.x)) {
ty = rp->min.y;
if(abs(ty - y) <= abs(dy))
dy = ty - y;
ty = rp->max.y;
if(abs(ty - y) <= abs(d))
d = ty - y;
}
}
}else {
for(i=0; i < nrect; i++) {
rp = &rects[i];
if((rp->min.y <= r->max.y) && (rp->max.y >= r->min.y)) {
tx = rp->min.x;
if(abs(tx - x) <= abs(d))
d = tx - x;
tx = rp->max.x;
if(abs(tx - x) <= abs(d))
d = tx - x;
}
ty = rp->max.y;
if(abs(ty - y) <= abs(dy))
dy = ty - y;
}
}
return d;
return dy;
}
static int
snap_vline(Rectangle *rects, int nrect, int dx, Rectangle *r, int x) {
Rectangle *rp;
int i, tx;
for(i=0; i < nrect; i++) {
rp = &rects[i];
if((rp->min.y <= r->max.y) && (rp->max.y >= r->min.y)) {
tx = rp->min.x;
if(abs(tx - x) <= abs(dx))
dx = tx - x;
tx = rp->max.x;
if(abs(tx - x) <= abs(dx))
dx = tx - x;
}
}
return dx;
}
/* Returns a gravity for increment handling. It's normally the opposite of the mask
@ -636,14 +640,14 @@ snap_rect(Rectangle *rects, int num, Rectangle *r, Align *mask, int snap) {
d.y = snap+1;
if(*mask&NORTH)
d.y = snap_line(rects, num, d.y, True, r, 0, r->min.y);
d.y = snap_hline(rects, num, d.y, r, r->min.y);
if(*mask&SOUTH)
d.y = snap_line(rects, num, d.y, True, r, 0, r->max.y);
d.y = snap_hline(rects, num, d.y, r, r->max.y);
if(*mask&EAST)
d.x = snap_line(rects, num, d.x, False, r, r->max.x, 0);
d.x = snap_vline(rects, num, d.x, r, r->max.x);
if(*mask&WEST)
d.x = snap_line(rects, num, d.x, False, r, r->min.x, 0);
d.x = snap_vline(rects, num, d.x, r, r->min.x);
ret = CENTER;
if(abs(d.x) <= snap)
@ -656,12 +660,13 @@ snap_rect(Rectangle *rects, int num, Rectangle *r, Align *mask, int snap) {
else
d.y = 0;
rect_morph_xy(r, d, mask);
rect_morph(r, d, mask);
return ret ^ *mask;
}
/* Grumble... Messy... TODO: Rewrite. */
void
do_mouse_resize(Client *c, Bool opaque, Align align) {
mouse_resize(Client *c, bool opaque, Align align) {
XEvent ev;
Rectangle *rects;
Rectangle frect, origin;
@ -684,9 +689,9 @@ do_mouse_resize(Client *c, Bool opaque, Align align) {
origin = f->r;
frect = f->r;
rects = rects_of_view(f->area->view, &num, c->frame);
rects = view_rects(f->area->view, &num, c->frame);
cur = cursor_of_quad(align);
cur = quad_cursor(align);
if((align==CENTER) && !opaque)
cur = cursor[CurSizing];
@ -704,7 +709,6 @@ do_mouse_resize(Client *c, Bool opaque, Align align) {
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;
@ -714,7 +718,7 @@ do_mouse_resize(Client *c, Bool opaque, Align align) {
warppointer(pt);
}
else if(f->client->fullscreen) {
XUngrabPointer(display, CurrentTime);
ungrabpointer();
return;
}
else if(!opaque) {
@ -745,13 +749,15 @@ do_mouse_resize(Client *c, Bool opaque, Align align) {
d.y = ev.xmotion.y_root;
if(align == CENTER && !opaque) {
SET(hrx);
SET(hry);
d.x = (d.x * hrx) - pt.x;
d.y = (d.y * hry) - pt.y;
}else
d = subpt(d, pt);
pt = addpt(pt, d);
rect_morph_xy(&origin, d, &align);
rect_morph(&origin, d, &align);
origin = constrain(origin);
frect = origin;
@ -761,10 +767,10 @@ do_mouse_resize(Client *c, Bool opaque, Align align) {
frect = constrain(frect);
//reshapewin(c->framewin, frect);
resize_client(c, &frect);
client_resize(c, frect);
break;
case ButtonRelease:
resize_client(c, &frect);
client_resize(c, frect);
if(!opaque) {
pt = translate(c->framewin, &scr.root,
@ -775,20 +781,21 @@ do_mouse_resize(Client *c, Bool opaque, Align align) {
}
free(rects);
XUngrabPointer(display, CurrentTime);
ungrabpointer();
return;
}
}
}
/* Doesn't belong here */
void
grab_button(XWindow w, uint button, ulong mod) {
XGrabButton(display, button, mod, w, False, ButtonMask,
GrabModeSync, GrabModeSync, None, None);
if((mod != AnyModifier) && (num_lock_mask != 0)) {
XGrabButton(display, button, mod | num_lock_mask, w, False, ButtonMask,
if((mod != AnyModifier) && (numlock_mask != 0)) {
XGrabButton(display, button, mod | numlock_mask, w, False, ButtonMask,
GrabModeSync, GrabModeAsync, None, None);
XGrabButton(display, button, mod | num_lock_mask | LockMask, w, False,
XGrabButton(display, button, mod | numlock_mask | LockMask, w, False,
ButtonMask, GrabModeSync, GrabModeAsync, None, None);
}
}

View File

@ -41,9 +41,6 @@
#include "dat.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <bio.h>
//#include "fns.h"
#include "printevent.h"
@ -96,13 +93,13 @@ unmask(Pair * list, uint val)
static char *
strhex(int key) {
sprintf(buffer, "0x%x", key);
sprint(buffer, "0x%x", key);
return buffer;
}
static char *
strdec(int key) {
sprintf(buffer, "%d", key);
sprint(buffer, "%d", key);
return buffer;
}
@ -656,14 +653,13 @@ VerbFocus(XEvent *e) {
static void
VerbKeymap(XEvent *e) {
XKeymapEvent *ev = &e->xkeymap;
int i;
int i;
fprintf(stderr, "window=0x%x%s", (int)ev->window, sep);
fprintf(stderr, "key_vector=");
fprint(2, "window=0x%x%s", (int)ev->window, sep);
fprint(2, "key_vector=");
for (i = 0; i < 32; i++)
fprintf(stderr, "%02x", ev->key_vector[i]);
fprintf(stderr, "\n");
fprint(2, "%02x", ev->key_vector[i]);
fprint(2, "\n");
}
static void
@ -935,7 +931,6 @@ VerbVisibility(XEvent *e) {
/******************************************************************************/
typedef struct Handler Handler;
struct Handler {
int key;
void (*fn)(XEvent*);
@ -945,9 +940,9 @@ void
printevent(XEvent *e) {
XAnyEvent *ev = &e->xany;
fprintf(stderr, "%3ld %-20s ", ev->serial, eventtype(e->xany.type));
fprint(2, "%3ld %-20s ", ev->serial, eventtype(e->xany.type));
if(ev->send_event)
fprintf(stderr, "(sendevent) ");
fprint(2, "(sendevent) ");
/*
fprintf(stderr, "type=%s%s", eventtype(e->xany.type), sep);
fprintf(stderr, "serial=%lu%s", ev->serial, sep);

View File

@ -5,8 +5,6 @@
#include "dat.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "fns.h"
/* basic rule matching language /regex/ -> value
@ -20,14 +18,15 @@ enum {
void
trim(char *str, const char *chars) {
const char *cp;
char *sp, *sn;
char *p, *q;
char c;
for(cp = chars; *cp; cp++) {
for(sp = sn = str; *sn; sn++) {
if(*sn != *cp)
*(sp++) = *sn;
}
*sp = 0;
for(cp = chars; (c = *cp); cp++) {
q = str;
for(p = q; *p; p++)
if(*p != c)
*q++ = *p;
*q = '\0';
}
}
@ -87,6 +86,6 @@ update_rules(Rule **rule, const char *data) {
*v++ = *p;
break;
default: /* can't happen */
assert(!"invalid state");
die("invalid state");
}
}

View File

@ -2,11 +2,10 @@
#include "dat.h"
#include <errno.h>
#include <iconv.h>
#include <string.h>
#include "fns.h"
char*
toutf8n(char *str, size_t nstr) {
toutf8n(const char *str, size_t nstr) {
static iconv_t cd;
char *buf, *pos;
size_t nbuf, bsize;
@ -33,7 +32,7 @@ toutf8n(char *str, size_t nstr) {
}
char*
toutf8(char *str) {
toutf8(const char *str) {
return toutf8n(str, strlen(str));
}

View File

@ -3,13 +3,10 @@
* See LICENSE file for license details.
*/
#include "dat.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "fns.h"
static Bool
is_empty(View *v) {
static bool
empty_p(View *v) {
Area *a;
for(a=v->area; a; a=a->next)
if(a->frame)
@ -17,86 +14,78 @@ is_empty(View *v) {
return True;
}
Frame *
view_clientframe(View *v, Client *c) {
Frame *f;
for(f=c->frame; f; f=f->cnext)
if(f->area->view == v)
break;
return f;
}
static void
assign_sel_view(View *v) {
_view_select(View *v) {
if(screen->sel != v) {
if(screen->sel)
write_event("UnfocusTag %s\n",screen->sel->name);
event("UnfocusTag %s\n",screen->sel->name);
screen->sel = v;
write_event("FocusTag %s\n", screen->sel->name);
event("FocusTag %s\n", screen->sel->name);
ewmh_updateview();
}
}
Client *
Client*
view_selclient(View *v) {
return v->sel && v->sel->sel ? v->sel->sel->client : nil;
}
View *
get_view(const char *name) {
View *v;
int cmp;
bool
view_fullscreen_p(View *v) {
Frame *f;
SET(cmp);
for(v = view; v; v=v->next)
if((cmp=strcmp(name, v->name)) >= 0)
break;
if(!v || cmp != 0)
v = create_view(name);
return v;
for(f=v->area->frame; f; f=f->anext)
if(f->client->fullscreen)
return true;
return false;
}
View *
create_view(const char *name) {
View*
view_create(const char *name) {
static ushort id = 1;
View **i, *v;
for(v=view; v; v=v->next)
if(!strcmp(name, v->name))
return v;
v = emallocz(sizeof(View));
v->id = id++;
utflcpy(v->name, name, sizeof(v->name));
write_event("CreateTag %s\n", v->name);
create_area(v, nil, 0);
new_column(v, v->area, 0);
event("CreateTag %s\n", v->name);
area_create(v, nil, 0);
column_new(v, v->area, 0);
focus_area(v->area->next);
area_focus(v->area->next);
for(i=&view; *i; i=&(*i)->next)
if(strcmp((*i)->name, name) < 0)
if(strcmp((*i)->name, name) >= 0)
break;
v->next = *i;
*i = v;
if(!screen->sel)
assign_sel_view(v);
_view_select(v);
ewmh_updateviews();
return v;
}
void
destroy_view(View *v) {
view_destroy(View *v) {
Area *a;
View **i, *tv;
while((a = v->area->next))
destroy_area(a);
destroy_area(v->area);
area_destroy(a);
area_destroy(v->area);
for(i=&view; *i; i=&(*i)->next)
if(*i == v) break;
*i = v->next;
write_event("DestroyTag %s\n", v->name);
event("DestroyTag %s\n", v->name);
if(v == screen->sel) {
for(tv=view; tv; tv=tv->next)
@ -104,9 +93,10 @@ destroy_view(View *v) {
if(tv == nil)
tv = view;
if(tv)
focus_view(screen, tv);
view_focus(screen, tv);
}
free(v);
ewmh_updateviews();
}
static void
@ -120,7 +110,7 @@ update_frame_selectors(View *v) {
}
void
focus_view(WMScreen *s, View *v) {
view_focus(WMScreen *s, View *v) {
Frame *f;
Client *c;
@ -128,114 +118,109 @@ focus_view(WMScreen *s, View *v) {
XGrabServer(display);
assign_sel_view(v);
_view_select(v);
update_frame_selectors(v);
update_divs();
div_update_all();
for(c=client; c; c=c->next)
if((f = c->sel)) {
if(f->view == v)
resize_client(c, &f->r);
client_resize(c, f->r);
else {
unmap_frame(c);
unmap_client(c, IconicState);
client_unmap(c, IconicState);
}
ewmh_updatestate(c);
ewmh_updateclient(c);
}
restack_view(v);
focus_area(v->sel);
draw_frames();
view_restack(v);
area_focus(v->sel);
frame_draw_all();
XSync(display, False);
sync();
XUngrabServer(display);
flushevents(EnterWindowMask, False);
}
void
select_view(const char *arg) {
view_select(const char *arg) {
char buf[256];
utflcpy(buf, arg, sizeof(buf));
trim(buf, " \t+/");
if(strlen(buf) == 0)
if(buf[0] == '\0')
return;
if(!strcmp(buf, ".") || !strcmp(buf, ".."))
return;
assign_sel_view(get_view(buf));
update_views(); /* performs focus_view */
_view_select(view_create(buf));
view_update_all(); /* performs view_focus */
}
void
attach_to_view(View *v, Frame *f) {
view_attach(View *v, Frame *f) {
Client *c;
Area *a;
c = f->client;
c->revert = nil;
a = v->sel;
if(c->trans || c->floating || c->fixedsize
|| c->titleless || c->borderless || c->fullscreen)
focus_area(v->area);
|| c->titleless || c->borderless || c->fullscreen
|| (c->w.ewmh.type & TypeDialog))
a = v->area;
else if(starting && v->sel->floating)
focus_area(v->area->next);
attach_to_area(v->sel, f);
a = v->area->next;
if(!(c->w.ewmh.type & TypeSplash))
area_focus(a);
area_attach(a, f);
}
void
restack_view(View *v) {
static XWindow *wins;
static uint winssz;
view_restack(View *v) {
static Vector_long wins;
Divide *d;
Frame *f;
Client *c;
Area *a;
uint n, i;
bool fscrn;
if(v != screen->sel)
return;
i = 0;
for(c = client; c; c = c->next)
i++;
if(i == 0)
return;
wins.n = 0;
fscrn = view_fullscreen_p(v);
for(a = v->area; a; a = a->next)
i++;
if(i >= winssz) {
winssz = 2 * i;
wins = erealloc(wins, sizeof(Window) * winssz);
}
n = 0;
wins[n++] = screen->barwin->w;
for(f = v->area->frame; f; f = f->anext)
if(f->client->fullscreen) {
n--;
break;
}
if(!fscrn)
vector_lpush(&wins, screen->barwin->w);
for(f=v->area->stack; f; f=f->snext)
wins[n++] = f->client->framewin->w;
vector_lpush(&wins, f->client->framewin->w);
if(fscrn)
vector_lpush(&wins, screen->barwin->w);
for(d = divs; d && d->w->mapped; d = d->next)
wins[n++] = d->w->w;
vector_lpush(&wins, d->w->w);
for(a=v->area->next; a; a=a->next)
if(a->frame) {
wins[n++] = a->sel->client->framewin->w;
vector_lpush(&wins, a->sel->client->framewin->w);
for(f=a->frame; f; f=f->anext)
if(f != a->sel)
wins[n++] = f->client->framewin->w;
vector_lpush(&wins, f->client->framewin->w);
}
if(n) {
XRaiseWindow(display, wins[0]);
XRestackWindows(display, wins, n);
ewmh_updatestacking();
if(wins.n) {
XRaiseWindow(display, wins.ary[0]);
XRestackWindows(display, (ulong*)wins.ary, wins.n);
}
}
void
scale_view(View *v, int w) {
view_scale(View *v, int w) {
uint xoff, numcol;
uint minwidth;
Area *a;
@ -285,28 +270,28 @@ scale_view(View *v, int w) {
}
void
arrange_view(View *v) {
view_arrange(View *v) {
uint xoff;
Area *a;
if(!v->area->next)
return;
scale_view(v, Dx(screen->r));
view_scale(v, Dx(screen->r));
xoff = 0;
for(a=v->area->next; a; a=a->next) {
a->r.min.x = xoff;
a->r.min.y = 0;
a->r.max.y = screen->brect.min.y;
xoff = a->r.max.x;
arrange_column(a, False);
column_arrange(a, False);
}
if(v == screen->sel)
update_divs();
div_update_all();
}
Rectangle *
rects_of_view(View *v, uint *num, Frame *ignore) {
Rectangle*
view_rects(View *v, uint *num, Frame *ignore) {
Rectangle *result;
Frame *f;
int i;
@ -328,98 +313,88 @@ rects_of_view(View *v, uint *num, Frame *ignore) {
return result;
}
/* XXX: This will need cleanup */
uchar *
char*
view_index(View *v) {
Rectangle *r;
Frame *f;
Area *a;
char *buf, *end;
uint i;
int i;
buf = buffer;
end = buffer+sizeof(buffer)-1;
for((a=v->area), (i=0); a && buf < end-1; (a=a->next), i++) {
bufclear();
for((a=v->area), (i=0); a; (a=a->next), i++) {
if(a->floating)
buf = seprint(buf, end, "# ~ %d %d\n",
Dx(a->r), Dy(a->r));
bufprint("# ~ %d %d\n", Dx(a->r), Dy(a->r));
else
buf = seprint(buf, end, "# %d %d %d\n",
i, a->r.min.x, Dx(a->r));
bufprint("# %d %d %d\n", i, a->r.min.x, Dx(a->r));
for(f=a->frame; f && buf < end-1; f=f->anext) {
for(f=a->frame; f; f=f->anext) {
r = &f->r;
if(a->floating)
buf = seprint(buf, end, "~ %C %d %d %d %d %s\n",
bufprint("~ %C %d %d %d %d %s\n",
f->client,
r->min.x, r->min.y,
Dx(*r), Dy(*r),
f->client->props);
else
buf = seprint(buf, end, "%d %C %d %d %s\n",
bufprint("%d %C %d %d %s\n",
i, f->client,
r->min.y, Dy(*r),
f->client->props);
}
}
return (uchar*)buffer;
return buffer;
}
uchar *
char*
view_ctl(View *v) {
Area *a;
char *buf, *end;
uint i;
buf = buffer;
end = buffer+sizeof(buffer)-1;
buf = seprint(buf, end, "%s\n", v->name);
bufclear();
bufprint("%s\n", v->name);
/* select <area>[ <frame>] */
buf = seprint(buf, end, "select %s", area_name(v->sel));
bufprint("select %s", area_name(v->sel));
if(v->sel->sel)
buf = seprint(buf, end, " %d", frame_idx(v->sel->sel));
buf = seprint(buf, end, "\n");
bufprint(" %d", frame_idx(v->sel->sel));
bufprint("\n");
/* select client <client> */
if(v->sel->sel)
buf = seprint(buf, end, "select client %C\n", v->sel->sel->client);
bufprint("select client %C\n", v->sel->sel->client);
for(a = v->area->next, i = 1; a && buf < end-1; a = a->next, i++) {
buf = seprint(buf, end, "colmode %d %s\n",
i, colmode2str(a->mode));
}
return (uchar*)buffer;
for(a = v->area->next, i = 1; a; a = a->next, i++)
bufprint("colmode %d %s\n", i, colmode2str(a->mode));
return buffer;
}
void
update_views(void) {
view_update_all(void) {
View *n, *v, *old;
Bool found;
int found;
old = screen->sel;
for(v=view; v; v=v->next)
update_frame_selectors(v);
found = False;
found = 0;
for(v=view; v; v=n) {
n=v->next;
if(v != old) {
if(is_empty(v))
destroy_view(v);
if(empty_p(v))
view_destroy(v);
else
found = True;
found++;
}
}
if(found && !strcmp(old->name, "nil") && is_empty(old))
destroy_view(old);
focus_view(screen, screen->sel);
if(found && !strcmp(old->name, "nil") && empty_p(old))
view_destroy(old);
view_focus(screen, screen->sel);
}
uint
newcolw(View *v, int num) {
view_newcolw(View *v, int num) {
Rule *r;
ulong n;
@ -438,3 +413,4 @@ newcolw(View *v, int num) {
}
return 0;
}

View File

@ -1,23 +1,34 @@
/* Copyright ©2007 Kris Maglione <fbsdaemon@gmail.com>
* See LICENSE file for license details.
*/
#define _X11_VISIBLE
#define ZP _ZP
#define ZR _ZR
#define pointerwin __pointerwin
#include "dat.h"
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <bio.h>
#include "fns.h"
#undef ZP /* These should be allocated in read-only memory, */
#undef ZR /* but declaring them const causes too much trouble
* elsewhere. */
#undef pointerwin
Point ZP = {0, 0};
Rectangle ZR = {{0, 0}, {0, 0}};
const Point ZP = {0, 0};
const Rectangle ZR = {{0, 0}, {0, 0}};
const Window _pointerwin = {
.w = PointerRoot
};
Window *const pointerwin = (Window*)&_pointerwin;
static Map wmap, amap;
static MapEnt *wbucket[137];
static MapEnt *abucket[137];
/* Rectangles/Points */
XRectangle
XRect(Rectangle r) {
XRectangle xr;
@ -95,6 +106,20 @@ rectsubpt(Rectangle r, Point p) {
return r;
}
/* Formatters */
static int
Afmt(Fmt *f) {
Atom a;
char *s;
int i;
a = va_arg(f->args, Atom);
s = XGetAtomName(display, a);
i = fmtprint(f, "%s", s);
free(s);
return i;
}
static int
Rfmt(Fmt *f) {
Rectangle r;
@ -143,13 +168,14 @@ initdisplay(void) {
amap.bucket = abucket;
amap.nhash = nelem(abucket);
fmtinstall('A', Afmt);
fmtinstall('R', Rfmt);
fmtinstall('P', Pfmt);
fmtinstall('W', Wfmt);
}
/* Images */
Image *
Image*
allocimage(int w, int h, int depth) {
Image *img;
@ -172,7 +198,7 @@ freeimage(Image *img) {
}
/* Windows */
Window *
Window*
createwindow(Window *parent, Rectangle r, int depth, uint class,
WinAttr *wa, int valmask)
{
@ -197,6 +223,15 @@ createwindow(Window *parent, Rectangle r, int depth, uint class,
return w;
}
Window*
window(XWindow w) {
static Window win;
win.type = WWindow;
win.w = w;
return &win;
}
void
reparentwindow(Window *w, Window *par, Point p) {
XReparentWindow(display, w->w, par->w, p.x, p.y);
@ -279,9 +314,9 @@ sethandler(Window *w, Handlers *new) {
assert((w->prev != nil && w->next != nil) || w->next == w->prev);
if(new == nil)
maprm(&wmap, (ulong)w->w);
map_rm(&wmap, (ulong)w->w);
else {
e = mapget(&wmap, (ulong)w->w, 1);
e = map_get(&wmap, (ulong)w->w, 1);
e->val = w;
}
old = w->handler;
@ -293,7 +328,7 @@ Window*
findwin(XWindow w) {
MapEnt *e;
e = mapget(&wmap, (ulong)w, 0);
e = map_get(&wmap, (ulong)w, 0);
if(e)
return e->val;
return nil;
@ -468,7 +503,7 @@ copyimage(Image *dst, Rectangle r, Image *src, Point p) {
}
/* Colors */
Bool
bool
namedcolor(char *name, ulong *ret) {
XColor c, c2;
@ -479,7 +514,7 @@ namedcolor(char *name, ulong *ret) {
return 0;
}
Bool
bool
loadcolor(CTuple *c, char *str) {
char buf[24];
@ -493,7 +528,7 @@ loadcolor(CTuple *c, char *str) {
}
/* Fonts */
Font *
Font*
loadfont(char *name) {
Biobuf *b;
Font *f;
@ -572,17 +607,43 @@ Atom
xatom(char *name) {
MapEnt *e;
e = hashget(&amap, name, 1);
e = hash_get(&amap, name, 1);
if(e->val == nil)
e->val = (void*)XInternAtom(display, name, False);
return (Atom)e->val;
}
void
sendevent(Window *w, bool propegate, long mask, XEvent *e) {
XSendEvent(display, w->w, propegate, mask, e);
}
KeyCode
keycode(char *name) {
return XKeysymToKeycode(display, XStringToKeysym(name));
}
void
sync(void) {
XSync(display, False);
}
/* Properties */
void
delproperty(Window *w, char *prop) {
XDeleteProperty(display, w->w, xatom(prop));
}
void
changeproperty(Window *w, char *prop, char *type, int width, uchar data[], int n) {
XChangeProperty(display, w->w, xatom(prop), xatom(type), width, PropModeReplace, data, n);
}
void
changeprop_string(Window *w, char *prop, char *string) {
changeprop_char(w, prop, "UTF8_STRING", string, strlen(string));
}
void
changeprop_char(Window *w, char *prop, char *type, char data[], int len) {
changeproperty(w, prop, type, 8, (uchar*)data, len);
@ -598,6 +659,25 @@ changeprop_long(Window *w, char *prop, char *type, long data[], int len) {
changeproperty(w, prop, type, 32, (uchar*)data, len);
}
void
changeprop_textlist(Window *w, char *prop, char *type, char *data[]) {
char **p, *s, *t;
int len, n;
len = 0;
for(p=data; *p; p++)
len += strlen(*p) + 1;
s = emalloc(len);
t = s;
for(p=data; *p; p++) {
n = strlen(*p) + 1;
memcpy(t, *p, n);
t += n;
}
changeprop_char(w, prop, type, s, len);
free(s);
}
void
freestringlist(char *list[]) {
XFreeStringList(list);
@ -626,6 +706,27 @@ getproperty(Window *w, char *prop, char *type, Atom *actual, ulong offset, uchar
return n;
}
char**
strlistdup(char *list[], int n) {
char **p, *q;
int i, m;
for(i=0, m=0; i < n; i++)
m += strlen(list[i])+1;
p = malloc((n+1)*sizeof(char*) + m);
q = (char*)&p[n+1];
for(i=0; i < n; i++) {
p[i] = q;
m = strlen(list[i])+1;
memcpy(q, list[i], m);
q += m;
}
p[n] = nil;
return p;
}
int
gettextlistproperty(Window *w, char *name, char **ret[]) {
XTextProperty prop;
@ -644,7 +745,7 @@ gettextlistproperty(Window *w, char *name, char **ret[]) {
return n;
}
char *
char*
gettextproperty(Window *w, char *name) {
char **list, *str;
int n;
@ -667,15 +768,25 @@ setfocus(Window *w, int mode) {
/* Mouse */
Point
querypointer(Window *w) {
XWindow dummy;
XWindow win;
Point pt;
uint ui;
int i;
XQueryPointer(display, w->w, &dummy, &dummy, &i, &i, &pt.x, &pt.y, &ui);
XQueryPointer(display, w->w, &win, &win, &i, &i, &pt.x, &pt.y, &ui);
return pt;
}
int
pointerscreen(void) {
XWindow win;
Point pt;
uint ui;
int i;
return XQueryPointer(display, scr.root.w, &win, &win, &i, &i, &pt.x, &pt.y, &ui);
}
void
warppointer(Point pt) {
XWarpPointer(display,
@ -771,18 +882,26 @@ sethints(Window *w) {
xs.win_gravity = NorthWestGravity;
switch (xs.win_gravity) {
case EastGravity: case CenterGravity: case WestGravity:
case EastGravity:
case CenterGravity:
case WestGravity:
p.y = 1;
break;
case SouthEastGravity: case SouthGravity: case SouthWestGravity:
case SouthEastGravity:
case SouthGravity:
case SouthWestGravity:
p.y = 2;
break;
}
switch (xs.win_gravity) {
case NorthGravity: case CenterGravity: case SouthGravity:
case NorthGravity:
case CenterGravity:
case SouthGravity:
p.x = 1;
break;
case NorthEastGravity: case EastGravity: case SouthEastGravity:
case NorthEastGravity:
case EastGravity:
case SouthEastGravity:
p.x = 2;
break;
}
@ -820,7 +939,7 @@ sizehint(WinHints *h, Rectangle r) {
p2 = h->aspect.max;
if(p.x * p2.y / p.y > p2.x)
r.max.x = h->baspect.x + p.y * p2.x / p2.y;
return rectaddpt(r, o);
}

View File

@ -1,119 +0,0 @@
#define Window XWindow
#define Font XFont
#define Screen XScreen
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/shape.h>
#undef Window
#undef Font
#undef Screen
typedef struct Point Point;
typedef struct Rectangle Rectangle;
typedef struct Screen Screen;
typedef struct Window Window;
typedef struct WinHints WinHints;
typedef struct Handlers Handlers;
typedef struct Window Image;
typedef struct Font Font;
typedef XSetWindowAttributes WinAttr;
struct Point {
int x, y;
};
struct Rectangle {
Point min, max;
};
struct Window {
int type;
XWindow w;
Window *parent;
Drawable image;
GC gc;
Rectangle r;
void *aux;
Handlers *handler;
Window *next, *prev;
WinHints *hints;
Bool mapped;
int unmapped;
int depth;
};
struct WinHints {
Point min, max;
Point base, baspect;
Point inc;
Rectangle aspect;
Point grav;
Bool gravstatic;
Bool position;
};
struct Handlers {
void (*bdown)(Window*, XButtonEvent*);
void (*bup)(Window*, XButtonEvent*);
void (*kdown)(Window*, XKeyEvent*);
void (*kup)(Window*, XKeyEvent*);
void (*focusin)(Window*, XFocusChangeEvent*);
void (*focusout)(Window*, XFocusChangeEvent*);
void (*enter)(Window*, XCrossingEvent*);
void (*leave)(Window*, XCrossingEvent*);
void (*motion)(Window*, XMotionEvent*);
void (*destroy)(Window*, XDestroyWindowEvent*);
void (*configreq)(Window*, XConfigureRequestEvent*);
void (*map)(Window*, XMapEvent*);
void (*unmap)(Window*, XUnmapEvent*);
void (*property)(Window*, XPropertyEvent*);
void (*expose)(Window*, XExposeEvent*);
};
struct Screen {
int screen;
Window root;
Colormap colormap;
Visual *visual;
Rectangle rect;
GC gc;
int depth;
int fd;
ulong black, white;
};
enum { WWindow, WImage };
struct Font {
XFontStruct *xfont;
XFontSet set;
int ascent;
int descent;
uint height;
char *name;
};
Display *display;
Screen scr;
extern Point ZP;
extern Rectangle ZR;
Rectangle insetrect(Rectangle r, int n);
Point Pt(int x, int y);
Rectangle Rect(int x0, int y0, int x1, int y1);
Rectangle Rpt(Point min, Point max);
XRectangle XRect(Rectangle r);
#define Dx(r) ((r).max.x - (r).min.x)
#define Dy(r) ((r).max.y - (r).min.y)
#define Pt(x, y) ((Point){(x), (y)})
#define Rpt(p, q) ((Rectangle){p, q})
#define Rect(x0, y0, x1, y1) ((Rectangle){Pt(x0, y0), Pt(x1, y1)})
#define changeprop(w, prop, type, data, n) \
changeproperty(w, prop, type, \
((sizeof(*(data)) == 8 ? 4 : sizeof(*(data))) * 8), \
(uchar*)(data), n)

View File

@ -9,10 +9,14 @@ for i in "$PLAN9" `echo P9PATHS`; do
fi
done
if [ ! -n "$RC" ]; then
if [ -n "$RC" ]; then
exit 1
fi
if [ ! -x "$PLAN9/bin/read" ]; then
echo 1>&2 $0: Found rc, but not read'(1)'. You probably have an out-of-date 9base installed.
fi
if [ -n "$1" ]; then
exec "$RC" "$@"
else

View File

@ -17,9 +17,9 @@ static IxpClient *client;
static void
usage(void) {
fprint(1,
"usage: %1$s [-a <address>] {create | read | ls [-ld] | remove | rm | write} <file>\n"
" %1$s [-a <address>] xwrite <file> <data>\n"
" %1$s -v\n", argv0);
"usage: %s [-a <address>] {create | read | ls [-ld] | remove | rm | write} <file>\n"
" %s [-a <address>] xwrite <file> <data>\n"
" %s -v\n", argv0, argv0, argv0);
exit(1);
}
@ -185,6 +185,7 @@ xcreate(int argc, char *argv[]) {
static int
xremove(int argc, char *argv[]) {
char *file;
int n;
ARGBEGIN{
default:
@ -192,8 +193,12 @@ xremove(int argc, char *argv[]) {
}ARGEND;
file = EARGF(usage());
if(ixp_remove(client, file) == 0)
fatal("Can't remove file '%s': %r\n", file);
do {
if(ixp_remove(client, file) == 0) {
fprint(2, "%s: Can't remove file '%s': %r\n", argv0, file);
n++;
}
}while((file = ARGF()));
return 0;
}
@ -208,18 +213,22 @@ xread(int argc, char *argv[]) {
usage();
}ARGEND;
if(argc == 0)
usage();
file = EARGF(usage());
fid = ixp_open(client, file, P9_OREAD);
if(fid == nil)
fatal("Can't open file '%s': %r\n", file);
do {
fid = ixp_open(client, file, P9_OREAD);
if(fid == nil)
fatal("Can't open file '%s': %r\n", file);
buf = emalloc(fid->iounit);
while((count = ixp_read(fid, buf, fid->iounit)) > 0)
write(1, buf, count);
ixp_close(fid);
buf = emalloc(fid->iounit);
while((count = ixp_read(fid, buf, fid->iounit)) > 0)
write(1, buf, count);
ixp_close(fid);
if(count == -1)
fatal("cannot read file/directory '%s': %r\n", file);
if(count == -1)
fprint(2, "%s: cannot read file/directory '%s': %r\n", argv0, file);
}while((file = ARGF()));
return 0;
}
@ -299,6 +308,7 @@ struct exectab {
{"write", xwrite},
{"xwrite", xawrite},
{"read", xread},
{"cat", xread},
{"create", xcreate},
{"remove", xremove},
{"rm", xremove},
@ -308,7 +318,7 @@ struct exectab {
int
main(int argc, char *argv[]) {
char *cmd, *address;
char *address;
exectab *tab;
int ret;
@ -327,8 +337,6 @@ main(int argc, char *argv[]) {
usage();
}ARGEND;
cmd = EARGF(usage());
if(!address)
fatal("$WMII_ADDRESS not set\n");
@ -337,7 +345,7 @@ main(int argc, char *argv[]) {
fatal("can't mount: %r\n");
for(tab = etab; tab->cmd; tab++)
if(strcmp(cmd, tab->cmd) == 0) break;
if(strcmp(*argv, tab->cmd) == 0) break;
if(tab->cmd == 0)
usage();

View File

@ -1,7 +1,12 @@
#!/bin/sh -f
# start wmiirc
export WMII_CONFPATH="$HOME/.wmii-CONFVERSION:CONFPREFIX/wmii-CONFVERSION"
export home="$HOME"
lconf="$home/.wmii-CONFVERSION"
gconf="CONFPREFIX/.wmii-CONFVERSION"
export WMII_CONFPATH="$conf:$gconf"
export POSIXLY_CORRECT=gnu_hippies
if wmii9rc; then
WMIIRC=`PATH="$WMII_CONFPATH:$PATH" which rc.wmii`
@ -9,5 +14,6 @@ else
WMIIRC=`PATH="$WMII_CONFPATH:$PATH" which wmiirc`
fi
mkdir $HOME/.wmii-CONFVERSION 2>/dev/null && CONFPREFIX/wmii-CONFVERSION/welcome &
exec "$WMIIRC" $@
mkdir $conf 2>/dev/null && $gconf/welcome &
exec "$WMIIRC" "$@"

View File

@ -9,9 +9,10 @@ iconscale = `{*=$epsbox; hoc -e $iconwidth/'('$3-' '$1')'}
iconheight = `{*=$epsbox; hoc -e '('$4-' '$2')*'$iconscale}
icon.png: $eps
x = `{hoc -e -'('$epsbox(1)^')'}
y = `{hoc -e -'('$epsbox(2)^')'}
gs -q -dBATCH -dNOPAUSE -sDEVICE=pngalpha -sOutputFile=$target -g^$iconwidth^x^$iconheight - <<!
* = `{hoc -e'-('$epsbox')'}
x = $1
y = $2
gs -q -dBATCH -dNOPAUSE -sDEVICE=pngalpha -sOutputFile=$target -g$iconwidth'x'$iconheight - <<!
$iconscale $iconscale scale
$x $y translate
($eps) run

View File

@ -108,41 +108,41 @@ extern int (*fmtdoquote)(int);
#endif
/* Edit .+1,/^$/ | cfn $PLAN9/src/lib9/fmt/?*.c | grep -v static |grep -v __ */
int dofmt(Fmt *f, const char *fmt);
int dorfmt(Fmt *f, const Rune *fmt);
double fmtcharstod(int(*f)(void*), void *vp);
int fmtfdflush(Fmt *f);
int fmtfdinit(Fmt *f, int fd, char *buf, int size);
int fmtinstall(int c, int (*f)(Fmt*));
int fmtprint(Fmt *f, const char *fmt, ...);
int fmtrune(Fmt *f, int r);
int fmtrunestrcpy(Fmt *f, Rune *s);
int fmtstrcpy(Fmt *f, const char *s);
char* fmtstrflush(Fmt *f);
int fmtstrinit(Fmt *f);
double fmtstrtod(const char *as, char **aas);
int fmtvprint(Fmt *f, const char *fmt, va_list args);
int fprint(int fd, const char *fmt, ...);
int print(const char *fmt, ...);
int dofmt(Fmt*, const char *fmt);
int dorfmt(Fmt*, const Rune *fmt);
double fmtcharstod(int(*f)(void*), void*);
int fmtfdflush(Fmt*);
int fmtfdinit(Fmt*, int fd, char *buf, int size);
int fmtinstall(int, int (*f)(Fmt*));
int fmtprint(Fmt*, const char*, ...);
int fmtrune(Fmt*, int);
int fmtrunestrcpy(Fmt*, Rune*);
int fmtstrcpy(Fmt*, const char*);
char* fmtstrflush(Fmt*);
int fmtstrinit(Fmt*);
double fmtstrtod(const char*, char**);
int fmtvprint(Fmt*, const char*, va_list);
int fprint(int, const char*, ...);
int print(const char*, ...);
void quotefmtinstall(void);
int quoterunestrfmt(Fmt *f);
int quotestrfmt(Fmt *f);
Rune* runefmtstrflush(Fmt *f);
int runefmtstrinit(Fmt *f);
Rune* runeseprint(Rune *buf, Rune *e, const char *fmt, ...);
Rune* runesmprint(const char *fmt, ...);
int runesnprint(Rune *buf, int len, const char *fmt, ...);
int runesprint(Rune *buf, const char *fmt, ...);
Rune* runevseprint(Rune *buf, Rune *e, const char *fmt, va_list args);
Rune* runevsmprint(const char *fmt, va_list args);
int runevsnprint(Rune *buf, int len, const char *fmt, va_list args);
char* seprint(char *buf, char *e, const char *fmt, ...);
char* smprint(const char *fmt, ...);
int snprint(char *buf, int len, const char *fmt, ...);
int sprint(char *buf, const char *fmt, ...);
int vfprint(int fd, const char *fmt, va_list args);
char* vseprint(char *buf, char *e, const char *fmt, va_list args);
char* vsmprint(const char *fmt, va_list args);
int vsnprint(char *buf, int len, const char *fmt, va_list args);
int quoterunestrfmt(Fmt*);
int quotestrfmt(Fmt*);
Rune* runefmtstrflush(Fmt*);
int runefmtstrinit(Fmt*);
Rune* runeseprint(Rune*,Rune*, const char*, ...);
Rune* runesmprint(const char*, ...);
int runesnprint(Rune*, int, const char*, ...);
int runesprint(Rune*, const char*, ...);
Rune* runevseprint(Rune*, Rune *, const char*, va_list);
Rune* runevsmprint(const char*, va_list);
int runevsnprint(Rune*, int, const char*, va_list);
char* seprint(char*, char*, const char*, ...);
char* smprint(const char*, ...);
int snprint(char*, int, const char *, ...);
int sprint(char*, const char*, ...);
int vfprint(int, const char*, va_list);
char* vseprint(char*, char*, const char*, va_list);
char* vsmprint(const char*, va_list);
int vsnprint(char*, int, const char*, va_list);
#endif

View File

@ -9,11 +9,12 @@
# ifndef USED
# define USED(x) if(x);else
# endif
# define uchar _p9uchar
# define ushort _p9ushort
# define uint _p9uint
# define ulong _p9ulong
#endif
#define uchar _p9uchar
#define ushort _p9ushort
#define uint _p9uint
#define ulong _p9ulong
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;

View File

@ -16,13 +16,11 @@ typedef struct Reprog Reprog;
* Sub expression matches
*/
struct Resub{
union
{
union {
char *sp;
Rune *rsp;
}s;
union
{
union {
char *ep;
Rune *rep;
}e;

View File

@ -14,34 +14,34 @@ enum
/* Edit .+1,/^$/ | cfn $PLAN9/src/lib9/utf/?*.c | grep -v static |grep -v __ */
int chartorune(Rune *rune, const char *str);
int fullrune(const char *str, int n);
int isalpharune(Rune c);
int islowerrune(Rune c);
int isspacerune(Rune c);
int istitlerune(Rune c);
int isupperrune(Rune c);
int runelen(long c);
int runenlen(Rune *r, int nrune);
Rune* runestrcat(Rune *s1, Rune *s2);
Rune* runestrchr(Rune *s, Rune c);
int runestrcmp(Rune *s1, Rune *s2);
Rune* runestrcpy(Rune *s1, Rune *s2);
Rune* runestrdup(Rune *s) ;
Rune* runestrecpy(Rune *s1, Rune *es1, Rune *s2);
long runestrlen(Rune *s);
Rune* runestrncat(Rune *s1, Rune *s2, long n);
int runestrncmp(Rune *s1, Rune *s2, long n);
Rune* runestrncpy(Rune *s1, Rune *s2, long n);
Rune* runestrrchr(Rune *s, Rune c);
Rune* runestrstr(Rune *s1, Rune *s2);
int runetochar(char *str, Rune *rune);
Rune tolowerrune(Rune c);
Rune totitlerune(Rune c);
Rune toupperrune(Rune c);
char* utfecpy(char *to, char *e, const char *from);
int utflen(const char *s);
int utfnlen(const char *s, long m);
char* utfrrune(const char *s, long c);
char* utfrune(const char *s, long c);
char* utfutf(const char *s1, const char *s2);
int isalpharune(Rune);
int islowerrune(Rune);
int isspacerune(Rune);
int istitlerune(Rune);
int isupperrune(Rune);
int runelen(Rune);
int runenlen(const Rune*, int);
Rune* runestrcat(Rune*, const Rune*);
Rune* runestrchr(const Rune*, Rune);
int runestrcmp(const Rune*, const Rune*);
Rune* runestrcpy(Rune*, const Rune*);
Rune* runestrdup(const Rune*) ;
Rune* runestrecpy(Rune*, Rune *e, const Rune*);
long runestrlen(const Rune*);
Rune* runestrncat(Rune*, const Rune*, long);
int runestrncmp(const Rune*, const Rune*, long);
Rune* runestrncpy(Rune*, const Rune*, long);
Rune* runestrrchr(const Rune*, Rune);
Rune* runestrstr(const Rune*, const Rune*);
int runetochar(char*, const Rune*);
Rune tolowerrune(Rune);
Rune totitlerune(Rune);
Rune toupperrune(Rune);
char* utfecpy(char*, char*, const char*);
int utflen(const char*);
int utfnlen(const char*, long);
char* utfrrune(const char*, long);
char* utfrune(const char*, long);
char* utfutf(const char*, const char*);
#endif

View File

@ -8,63 +8,69 @@
#undef ulong
#undef uvlong
#undef vlong
#ifndef KENC
# define uchar _wmiiuchar
# define ushort _wmiiushort
# define uint _wmiiuint
# define ulong _wmiiulong
# define vlong _wmiivlong
# define uvlong _wmiiuvlong
#endif
#define uchar _x_uchar
#define ushort _x_ushort
#define uint _x_uint
#define ulong _x_ulong
#define uvlong _x_uvlong
#define vlong _x_vlong
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned long long uvlong;
typedef long long vlong;
typedef long long vlong;
#define strlcat wmii_strlcat
/* util.c */
uint tokenize(char *res[], uint reslen, char *str, char delim);
char *estrdup(const char *str);
void *erealloc(void *ptr, uint size);
void *emallocz(uint size);
void *emalloc(uint size);
void fatal(const char *fmt, ...);
int max(int a, int b);
int min(int a, int b);
char *str_nil(char *s);
int utflcpy(char *to, const char *from, int l);
uint strlcat(char *dst, const char *src, unsigned int siz);
void _die(char*, int, char*);
void* emalloc(uint);
void* emallocz(uint);
void* erealloc(void*, uint);
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);
uint tokenize(char **, uint, char*, char);
int utflcpy(char*, const char*, int);
#define die(x) \
_die(__FILE__, __LINE__, x)
char *argv0;
void *__p;
int __i;
#undef ARGBEGIN
#undef ARGEND
#undef ARGF
#undef EARGF
#define ARGBEGIN \
int _argi=0, _argtmp=0, _inargv=0; char *_argv=nil; \
if(!argv0) argv0=ARGF(); \
int _argtmp=0, _inargv=0; char *_argv=nil; \
if(!argv0) argv0=*argv; argv++, argc--; \
_inargv=1; USED(_inargv); \
while(argc && argv[0][0] == '-') { \
_argi=1; _argv=*argv++; argc--; \
while(_argv[_argi]) switch(_argv[_argi++])
#define ARGEND }_inargv=0;USED(_argtmp);USED(_argv);USED(_argi);USED(_inargv)
_argv=&argv[0][1]; argv++; argc--; \
if(_argv[0] == '-' && _argv[1] == '\0') \
break; \
while(*_argv) switch(*_argv++)
#define ARGEND }_inargv=0;USED(_argtmp, _argv, _inargv)
#define ARGF() ((_inargv && _argv[_argi]) ? \
(_argtmp=_argi, _argi=strlen(_argv), __i=_argi,_argv+_argtmp) \
: ((argc > 0) ? (--argc, ++argv, __i=argc, __p=argv, *(argv-1)) : ((char*)0)))
#define EARGF(f) ((_inargv && _argv[_argi]) ? \
(_argtmp=_argi, _argi=strlen(_argv), __i=_argi, _argv+_argtmp) \
: ((argc > 0) ? (--argc, ++argv, __i=argc, __p=argv, *(argv-1)) : ((f), (char*)0)))
#define EARGF(f) ((_inargv && *_argv) ? \
(_argtmp=strlen(_argv), _argv+=_argtmp, _argv-_argtmp) \
: ((argc > 0) ? \
(--argc, ++argv, _used(argc), *(argv-1)) \
: ((f), (char*)0)))
#define ARGF() EARGF(_used(0))
static inline void
_used(long a, ...) {
if(a){}
}
#ifndef KENC
# undef USED
# undef SET
# define USED(x) if(x){}else
# define SET(x) ((x)=0)
# undef USED
# undef SET
# define USED(...) _used((long)__VA_ARGS__)
# define SET(x) USED(&x)
#endif

228
include/x11.h Normal file
View File

@ -0,0 +1,228 @@
#define Window XWindow
#define Font XFont
#define Screen XScreen
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#ifdef _X11_VISIBLE
# include <X11/Xatom.h>
# include <X11/extensions/shape.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,
};
typedef enum Align Align;
typedef struct CTuple CTuple;
typedef struct Point Point;
typedef struct Rectangle Rectangle;
typedef struct Screen Screen;
typedef struct Ewmh Ewmh;
typedef struct Window Window;
typedef struct WinHints WinHints;
typedef struct Handlers Handlers;
typedef struct Window Image;
typedef struct Font Font;
typedef XSetWindowAttributes WinAttr;
struct CTuple {
ulong bg;
ulong fg;
ulong border;
char colstr[24]; /* #RRGGBB #RRGGBB #RRGGBB */
};
struct Point {
int x, y;
};
struct Rectangle {
Point min, max;
};
struct Ewmh {
long type;
};
struct Window {
int type;
XWindow w;
Window *parent;
Drawable image;
GC gc;
Rectangle r;
void *aux;
Handlers *handler;
Window *next, *prev;
WinHints *hints;
Ewmh ewmh;
bool mapped;
int unmapped;
int depth;
};
struct WinHints {
Point min, max;
Point base, baspect;
Point inc;
Rectangle aspect;
Point grav;
bool gravstatic;
bool position;
};
struct Handlers {
void (*bdown)(Window*, XButtonEvent*);
void (*bup)(Window*, XButtonEvent*);
void (*kdown)(Window*, XKeyEvent*);
void (*kup)(Window*, XKeyEvent*);
void (*focusin)(Window*, XFocusChangeEvent*);
void (*focusout)(Window*, XFocusChangeEvent*);
void (*enter)(Window*, XCrossingEvent*);
void (*leave)(Window*, XCrossingEvent*);
void (*motion)(Window*, XMotionEvent*);
void (*destroy)(Window*, XDestroyWindowEvent*);
void (*configreq)(Window*, XConfigureRequestEvent*);
void (*map)(Window*, XMapEvent*);
void (*unmap)(Window*, XUnmapEvent*);
void (*property)(Window*, XPropertyEvent*);
void (*expose)(Window*, XExposeEvent*);
};
struct Screen {
int screen;
Window root;
Colormap colormap;
Visual *visual;
Rectangle rect;
GC gc;
int depth;
int fd;
ulong black, white;
};
enum { WWindow, WImage };
struct Font {
XFontStruct *xfont;
XFontSet set;
int ascent;
int descent;
uint height;
char *name;
};
#ifdef VARARGCK
# pragma varargck type "A" Atom
# pragma varargck type "W" Window*
# pragma varargck type "P" Point
# pragma varargck type "R" Rectangle
#endif
Display *display;
Screen scr;
extern Point ZP;
extern Rectangle ZR;
extern Window* pointerwin;
Rectangle insetrect(Rectangle r, int n);
Point Pt(int x, int y);
Rectangle Rect(int x0, int y0, int x1, int y1);
Rectangle Rpt(Point min, Point max);
XRectangle XRect(Rectangle r);
#define Dx(r) ((r).max.x - (r).min.x)
#define Dy(r) ((r).max.y - (r).min.y)
#define Pt(x, y) ((Point){(x), (y)})
#define Rpt(p, q) ((Rectangle){p, q})
#define Rect(x0, y0, x1, y1) ((Rectangle){Pt(x0, y0), Pt(x1, y1)})
#define changeprop(w, prop, type, data, n) \
changeproperty(w, prop, type, \
((sizeof(*(data)) == 8 ? 4 : sizeof(*(data))) * 8), \
(uchar*)(data), n)
/* x11.c */
Window *createwindow(Window *parent, Rectangle, int depth, uint class, WinAttr*, int valuemask);
char *gettextproperty(Window*, char*);
Point addpt(Point, Point);
Image* allocimage(int w, int h, int depth);
void border(Image *dst, Rectangle, int w, ulong col);
void changeprop_char(Window*, char*, char*, char[], int);
void changeprop_long(Window*, char*, char*, long[], int);
void changeprop_short(Window*, char*, char*, short[], int);
void changeprop_string(Window*, char*, char*);
void changeprop_textlist(Window*, char*, char*, char*[]);
void changeproperty(Window*, char*, char*, int width, uchar*, int);
void copyimage(Image*, Rectangle, Image*, Point);
void delproperty(Window*, char*);
void destroywindow(Window*);
Point divpt(Point, Point);
void drawline(Image*, Point, Point, int cap, int w, ulong col);
void drawpoly(Image*, Point*, int, int cap, int w, ulong col);
void drawstring(Image*, Font*, Rectangle, Align, char*, ulong col);
int eqpt(Point, Point);
int eqrect(Rectangle, Rectangle);
void fill(Image*, Rectangle, ulong col);
void fillpoly(Image*, Point*, int, ulong col);
Window* findwin(XWindow);
void freefont(Font*);
void freeimage(Image *);
void freestringlist(char**);
ulong getproperty(Window*, char *prop, char *type, Atom *actual, ulong offset, uchar **ret, ulong length);
int gettextlistproperty(Window *w, char *name, char **ret[]);
int grabpointer(Window*, Window *confine, Cursor, int mask);
void initdisplay(void);
KeyCode keycode(char*);
uint labelh(Font*);
bool loadcolor(CTuple*, char*);
Font* loadfont(char*);
void lowerwin(Window*);
int mapwin(Window*);
void movewin(Window*, Point);
Point mulpt(Point p, Point q);
bool namedcolor(char *name, ulong*);
int pointerscreen(void);
Point querypointer(Window*);
void raisewin(Window*);
void reparentwindow(Window*, Window*, Point);
void reshapewin(Window*, Rectangle);
void sendevent(Window*, bool propegate, long mask, XEvent*);
void setfocus(Window*, int mode);
void sethints(Window*);
void setshapemask(Window *dst, Image *src, Point);
void setwinattr(Window*, WinAttr*, int valmask);
Point subpt(Point, Point);
char** strlistdup(char**, int);
void sync(void);
uint textwidth(Font*, char*);
uint textwidth_l(Font*, char*, uint len);
Point translate(Window*, Window*, Point);
void ungrabpointer(void);
int unmapwin(Window*);
void warppointer(Point);
Window* window(XWindow);
uint winprotocols(Window*);
Atom xatom(char*);
Handlers* sethandler(Window*, Handlers*);
XRectangle XRect(Rectangle);
Rectangle gravitate(Rectangle dst, Rectangle src, Point grav);
Rectangle insetrect(Rectangle, int);
Rectangle rectaddpt(Rectangle, Point);
Rectangle rectsubpt(Rectangle, Point);
Rectangle sizehint(WinHints*, Rectangle);

View File

@ -97,7 +97,7 @@ bad:
}
int
runetochar(char *str, Rune *rune)
runetochar(char *str, const Rune *rune)
{
long c;
@ -132,17 +132,15 @@ runetochar(char *str, Rune *rune)
}
int
runelen(long c)
runelen(Rune c)
{
Rune rune;
char str[10];
rune = c;
return runetochar(str, &rune);
return runetochar(str, &c);
}
int
runenlen(Rune *r, int nrune)
runenlen(const Rune *r, int nrune)
{
int nb, c;

View File

@ -16,7 +16,7 @@
#include <plan9.h>
Rune*
runestrcat(Rune *s1, Rune *s2)
runestrcat(Rune *s1, const Rune *s2)
{
runestrcpy(runestrchr(s1, 0), s2);

View File

@ -17,7 +17,7 @@
#include "utf.h"
Rune*
runestrchr(Rune *s, Rune c)
runestrchr(const Rune *s, Rune c)
{
Rune c0 = c;
Rune c1;
@ -25,11 +25,11 @@ runestrchr(Rune *s, Rune c)
if(c == 0) {
while(*s++)
;
return s-1;
return (Rune*)s-1;
}
while(c1 = *s++)
if(c1 == c0)
return s-1;
return (Rune*)s-1;
return 0;
}

View File

@ -17,7 +17,7 @@
#include "utf.h"
int
runestrcmp(Rune *s1, Rune *s2)
runestrcmp(const Rune *s1, const Rune *s2)
{
Rune c1, c2;

View File

@ -17,7 +17,7 @@
#include "utf.h"
Rune*
runestrcpy(Rune *s1, Rune *s2)
runestrcpy(Rune *s1, const Rune *s2)
{
Rune *os1;

View File

@ -15,7 +15,7 @@
#include <plan9.h>
Rune*
runestrdup(Rune *s)
runestrdup(const Rune *s)
{
Rune *ns;

View File

@ -17,7 +17,7 @@
#include "utf.h"
Rune*
runestrecpy(Rune *s1, Rune *es1, Rune *s2)
runestrecpy(Rune *s1, Rune *es1, const Rune *s2)
{
if(s1 >= es1)
return s1;

View File

@ -14,7 +14,7 @@
#include <plan9.h>
long
runestrlen(Rune *s)
runestrlen(const Rune *s)
{
return runestrchr(s, 0) - s;

View File

@ -17,7 +17,7 @@
#include "utf.h"
Rune*
runestrncat(Rune *s1, Rune *s2, long n)
runestrncat(Rune *s1, const Rune *s2, long n)
{
Rune *os1;

View File

@ -17,7 +17,7 @@
#include "utf.h"
int
runestrncmp(Rune *s1, Rune *s2, long n)
runestrncmp(const Rune *s1, const Rune *s2, long n)
{
Rune c1, c2;

View File

@ -17,7 +17,7 @@
#include "utf.h"
Rune*
runestrncpy(Rune *s1, Rune *s2, long n)
runestrncpy(Rune *s1, const Rune *s2, long n)
{
int i;
Rune *os1;

View File

@ -17,14 +17,14 @@
#include "utf.h"
Rune*
runestrrchr(Rune *s, Rune c)
runestrrchr(const Rune *s, Rune c)
{
Rune *r;
const Rune *r;
if(c == 0)
return runestrchr(s, 0);
r = 0;
while(s = runestrchr(s, c))
r = s++;
return r;
return (Rune*)r;
}

View File

@ -21,14 +21,15 @@
* 0 if none
*/
Rune*
runestrstr(Rune *s1, Rune *s2)
runestrstr(const Rune *s1, const Rune *s2)
{
Rune *p, *pa, *pb;
const Rune *pa, *pb;
Rune *p;
int c0, c;
c0 = *s2;
if(c0 == 0)
return s1;
return (Rune*)s1;
s2++;
for(p=runestrchr(s1, c0); p; p=runestrchr(p+1, c0)) {
pa = p;

View File

@ -1,17 +1,16 @@
CFLAGS += \
-std=c99 \
-pipe \
-pedantic \
-Wall \
-Wno-parentheses \
-Wno-missing-braces \
-Wno-switch \
-Wno-comment \
-Wno-sign-compare \
-Wno-uninitialized \
-Wno-unused-parameter \
-Wimplicit \
-Wreturn-type \
-Wtrigraphs \
-Wstrict-prototypes \
-Wmissing-prototypes \
-Wno-comment \
-Wno-missing-braces \
-Wno-parentheses \
-Wno-sign-compare \
-Wno-switch \
-Wpointer-arith \
-Wreturn-type \
-Wstrict-prototypes \
-Wtrigraphs \

View File

@ -1,45 +1,25 @@
#!/usr/bin/env wmii9rc
scriptname=$0
oldpath=$path; path=($PLAN9/bin $path)
. wmii.rc wmiirc # Include utility functions
# WMII Configuration
confpath=`{echo $WMII_CONFPATH | sed 'y/:/ /'}
oldpath=$path
path=($PLAN9/bin $path)
# Sanity checks
if(echo $0 | grep -s '(^|/)rc\.wmii\.local$') {
echo >[1=2] Fatal: This file must not be named rc.wmii.local
exit badname
}
fn config_whatis {
prog = `{@{path=$confpath whatis $1} | grep -v '^fn|= ' || echo /dev/null}
shift; echo $prog $*
}
if(! test -x $PLAN9/bin/read) {
echo 'Can''t find the ''read'' command' >[1=2]
xmessage -file - <<'!'
exec `{config_whatis wmiirc}
}
rc.wmii can't run:
You have a Plan 9 utilities installed, but are missing the 'read' command.
This likely means that you have an out-of-date 9base installed.
wmiirc will be run instead.
!
# Configurables
# Keys
MODKEY=Mod1
UP=k
DOWN=j
LEFT=h
RIGHT=l
WMII_FONT='-*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*'
WMII_NORMCOLORS=('#222222' '#5FBF77' '#2A7F3F')
WMII_FOCUSCOLORS=('#ffffff' '#153F1F' '#2A7F3F')
WMII_BACKGROUND='#333333'
# Theme
wmiifont='drift,-*-fixed-*-*-*-*-9-*-*-*-*-*-*-*'
wmiifont='-*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*'
wmiinormcol=`{echo '#222222 #5FBF77 #2A7F3F'}
wmiifocuscol=`{echo '#ffffff #153F1F #2A7F3F'}
wmiibackground='#333333'
# Programs
WMII_TERM=(xterm)
# Column Rules
@ -49,68 +29,33 @@ wmiir write /colrules <<!
# Tagging Rules
wmiir write /tagrules <<!
/VLC/ -> ~
/XMMS.*/ -> ~
/MPlayer.*/ -> ~
/.*/ -> sel
/.*/ -> 1
!
# Status Bar Info
fn status { echo -n `{uptime | sed 's/.*://; s/,//g'} '|' `{date} }
fn viewtitle { echo $* }
# Convenience Functions
fn wmiimenu {
dmenu -b -fn $WMII_FONT \
-nf $WMII_NORMCOLORS(1) -nb $WMII_NORMCOLORS(2) \
-sf $WMII_FOCUSCOLORS(1) -sb $WMII_FOCUSCOLORS(2)
fn status {
echo -n `{uptime | sed 's/.*://; s/,//g'} \
'|' `{date}
}
fn 9menu {
wmii9menu -font $WMII_FONT \
-^(nf nb br)^$WMII_NORMCOLORS \
-^(sf sb br)^$WMII_FOCUSCOLORS $*
}
# End Configuration
fn proglist {
/bin/ls -lL `{echo $* | sed 'y/:/ /'} >[2]/dev/null \
| awk '$1 ~ /^[^d].*x/ { print $NF }' \
| sort | uniq
}
fn actionlist {
{ proglist $WMII_CONFPATH
getfuns Action
} | sort | uniq
}
fn run_command { @{
rfork ns
path=$oldpath
eval exec $* &
}
}
fn getfuns { env | sed -n 's/^fn#'^$1^'-([^=]+).*/\1/p' }
fn initkeys { getfuns Key | wmiir write /keys }
fn read_tags { wmiir ls /tag | sed 's,/,,; /^sel$/d' }
fn 'fn?' {rc -c 'whatis '$1 >[2]/dev/null | grep -s '^fn ' }
ifs='' {nl=`{echo}}
confpath=`{echo $WMII_CONFPATH | sed 'y/:/ /'}
# Events
fn Event-Start {
switch($1) {
case wmiirc
rm -f $progs_file
exit
}
fn sigexit {
rm -f $progs_file
wi_cleankeys
}
fn Event-Key { Key-$1 $1 }
fn Event-CreateTag { echo $WMII_NORMCOLORS `{viewtitle $*} | wmiir create /lbar/$"* }
fn Event-CreateTag { echo $wmiinormcol $* | wmiir create /lbar/$"* }
fn Event-DestroyTag { wmiir remove /lbar/$"* }
fn Event-FocusTag { wmiir xwrite /lbar/$"* $WMII_FOCUSCOLORS `{viewtitle $*} }
fn Event-UnfocusTag { wmiir xwrite /lbar/$"* $WMII_NORMCOLORS `{viewtitle $*} }
fn Event-FocusTag { wmiir xwrite /lbar/$"* $wmiifocuscol $* }
fn Event-UnfocusTag { wmiir xwrite /lbar/$"* $wmiinormcol $* }
fn Event-UrgentTag { shift; wmiir xwrite /lbar/$"* '*'$"* }
fn Event-NotUrgentTag { shift; wmiir xwrite /lbar/$"* $"* }
@ -119,36 +64,38 @@ fn Event-LeftBarClick { shift; wmiir xwrite /ctl view $* }
fn Event-ClientMouseDown {
client = $1; button = $2
if(~ $button 3) {
do=`{9menu -initial $menulast Nop Delete Fullscreen}
do=`{wi_9menu -initial $menulast Nop Delete Fullscreen}
switch($do) {
case Delete
wmiir xwrite /client/$client/ctl kill
case Fullscreen
wmiir xwrite /client/$client/ctl Fullscreen on
}
if(! ~ $#do 0)
if(! ~ $do '')
menulast = $do;
}
}
menulast = Nop
# Utility
fn 'fn?' {rc -c 'whatis '$1 >[2]/dev/null | grep -s '^fn ' }
# Actions
fn Action {
cmd=$1 action=Action-$cmd { shift
if('fn?' $action)
$action $*
if not
run_command `{config_whatis $cmd} $*
wi_runcmd `{wi_script $cmd} $*
} &
}
# Actions
fn Action-rehash {
if(test -d /proc/$pid)
for(i in $WMII_NS_DIR/proglist.*) {
id=`{echo $i | sed 's/.*\.(.*)/\1/'} \
if(! test -d /proc/$id) rm $i
}
proglist $PATH >$progs_file
comm -23 <{ls $WMII_NS_DIR/proglist.* | awk -F'\.' '{print $NF}'} \
<{ps | awk '{print $2}'} |
while(id=`{read})
rm $WMII_NS_DIR/proglist.$id
wi_proglist $PATH >$progs_file
}
fn Action-quit { wmiir xwrite /ctl quit }
fn Action-exec { wmiir xwrite /ctl exec $* }
@ -156,24 +103,16 @@ fn Action-status {
flag x -; flag r -
if(wmiir remove /rbar/status >[2]/dev/null)
sleep 2
echo $WMII_NORMCOLORS | wmiir create /rbar/status
echo $wmiinormcol | wmiir create /rbar/status
while(status | wmiir write /rbar/status)
sleep 1
}
# Source Variables, &c
local = `{config_whatis rc.wmii.local}
. <{awk '//;
/^# Overrides/ {
print "xmessage -file - <<!"
print "rc.wmii: Warning:"
print " Your rc.wmii.local contains an ''# Overrides'' line."
print " This line has a deprecated special meaning. Functions"
print " you wish to override should be defined in a function"
print " called Action-overridekeys"
print "!"
exit
}' $local </dev/null}
if(~ $0 rc.wmii.local */rc.wmii.local)
wi_notice This file should not be named rc.wmii.local
if not
. `{wi_script rc.wmii.local} /dev/null
# Key Bindings
fn key {
@ -182,12 +121,15 @@ fn key {
~ $#key 0
}
# This is... ugly.
key $MODKEY-Control-t || fn $key {
switch(`{wmiir read /keys | wc -l}) {
case 0 1
initkeys
wmiir xwrite /ctl $keys
wmiir xwrite /ctl grabmod $MODKEY
case *
ifs=() { keys=`{wmiir read /keys} }
wmiir xwrite /keys $MODKEY-Control-t
wmiir xwrite /ctl grabmod Mod3
}
@ -213,37 +155,36 @@ key $MODKEY-m || fn $key { wmiir xwrite /tag/sel/ctl colmode sel max }
key $MODKEY-Shift-c || fn $key { wmiir xwrite /client/sel/ctl kill }
key $MODKEY-a || fn $key { Action `{actionlist | wmiimenu} & }
key $MODKEY-p || fn $key { ifs=() { run_command `{wmiimenu <$progs_file} & } }
key $MODKEY-Return || fn $key { run_command $WMII_TERM & }
key $MODKEY-a || fn $key { Action `{wi_actions | wi_menu} & }
key $MODKEY-p || fn $key { ifs=() { wi_runcmd `{wi_menu <$progs_file} & } }
key $MODKEY-Return || fn $key { wi_runcmd $WMII_TERM & }
key $MODKEY-t || fn $key { wmiir xwrite /ctl view `{read_tags | wmiimenu} & }
key $MODKEY-t || fn $key { wmiir xwrite /ctl view `{wi_tags | wi_menu} & }
key $MODKEY-Shift-t || fn $key {
sel = `{wmiir read /client/sel/ctl | sed 1q} \
wmiir xwrite /client/$sel/tags `{read_tags | wmiimenu} &
wmiir xwrite /client/$sel/tags `{wi_tags | wi_menu} &
}
key $MODKEY-^`{seq 0 9}|| fn $key { wmiir xwrite /ctl view `{echo $1 | sed 's/.*-//'} }
key $MODKEY-^`{seq 0 9} || fn $key {
wmiir xwrite /ctl view `{echo $1 | sed 's/.*-//'}
}
key Shift-$MODKEY-^`{seq 0 9} || fn $key {
wmiir xwrite /client/sel/tags `{echo $1 | sed 's/.*-//'}
}
# WM Configuration
wmiir write /ctl <<!
grabmod $MODKEY
border 2
font $WMII_FONT
focuscolors $WMII_FOCUSCOLORS
normcolors $WMII_NORMCOLORS
view 1
grabmod $MODKEY
border 2
font $wmiifont
focuscolors $wmiifocuscol
normcolors $wmiinormcol
!
xsetroot -solid $WMII_BACKGROUND
xsetroot -solid $wmiibackground
# Source Overrides
. <{awk '/^# Overrides/, 0' $local </dev/null}
if('fn?' Action-overridekeys)
Action-overridekeys
if not
. `{config_whatis overridekeys}
Action overridekeys
# Misc Setup
progs_file=$WMII_NS_DIR/proglist.$pid
@ -251,27 +192,16 @@ Action status
Action rehash
# Tag Bar Setup
ifs='#
'{ for(bar in `{comm -23 <{wmiir ls /lbar} <{read_tags}})
wmiir remove /lbar/$bar
ifs=$nl{
wmiir rm `{comm -23 <{wmiir ls /lbar} <{wi_tags}}
seltag=`{wmiir read /tag/sel/ctl | sed 1q}
for(tag in `{read_tags}) {
for(tag in `{wi_tags}) {
if(~ $tag $seltag)
echo $WMII_FOCUSCOLORS `{viewtitle $tag} | wmiir create /lbar/$tag
echo $wmiifocuscol $tag | wmiir create /lbar/$tag
if not
echo $WMII_NORMCOLORS `{viewtitle $tag} | wmiir create /lbar/$tag
echo $wmiinormcol $tag | wmiir create /lbar/$tag
}
}
# Keygrab Setup
initkeys
wi_eventloop
if(echo Start wmiirc | ! wmiir write /event >[2]/dev/null)
exit write
# Event Loop
wmiir read /event |
while(*=`{read}) {
event = $1; shift
Event-$event $*
} >[2]/dev/null </dev/null

View File

@ -45,8 +45,7 @@ echo '
/Firefox/ -> www
/XMMS.*/ -> ~
/MPlayer.*/ -> ~
/.*/ -> !
/.*/ -> 1
/.*/ -> sel
' >/tagrules
subfn seq {
@ -139,6 +138,7 @@ Event ClientMouseDown {
(client button) := $*
if {~ $button 3} {
lastcmd = `{9menu -initial $lastcmd Nop Delete Fullscreen}
if{~ $#lastcmd 0} {lastcmd=''}
cmp := {~ $lastcmd $*}
if {$cmp Nop} {
} {$cmp Delete} { echo kill >/client/$client/ctl

View File

@ -40,7 +40,7 @@ status() {
# Event processing
# Processed later by `wmiiloop' and evaled.
# Duplicate the eval line and replace 'eval' with 'echo' for details.
# Uncomment the line before the eval and run for details.
eventstuff() {
cat <<'!'
# Events
@ -168,6 +168,7 @@ export WMII_MENU WMII_9MENU WMII_FONT WMII_TERM
export WMII_FOCUSCOLORS WMII_SELCOLORS WMII_NORMCOLORS
# Feed events to `wmiiloop' for processing
#echo "$(eventstuff | sed 's/^[ ]//' | { . wmiiloop; })"
eval "$(eventstuff | sed 's/^[ ]//' | { . wmiiloop; })"
echo "$Keys" | tr ' ' '\n' | wmiir write /keys
@ -196,18 +197,14 @@ proglist $PATH >$progsfile &
xsetroot -solid "$WMII_BACKGROUND" &
# Setup Tag Bar
seltag="$(wmiir read /tag/sel/ctl 2>/dev/null)"
wmiir ls /lbar |
while read bar; do
wmiir remove "/lbar/$bar"
done
wmiir ls /tag | sed -e 's|/||; /^sel$/d' |
while read tag; do
if [ "X$tag" = "X$seltag" ]; then
echo "$WMII_FOCUSCOLORS" "$tag" | wmiir create "/lbar/$tag"
(IFS="$(echo)"; wmiir rm $(wmiir ls /lbar))
seltag="$(wmiir read /tag/sel/ctl 2>/dev/null | sed 1q)"
wmiir ls /tag | sed -e 's|/||; /^sel$/d' | while read tag; do
if [ "$tag" = "$seltag" ]; then
echo "$WMII_FOCUSCOLORS" "$tag"
else
echo "$WMII_NORMCOLORS" "$tag" | wmiir create "/lbar/$tag"
fi
echo "$WMII_NORMCOLORS" "$tag"
fi | wmiir create "/lbar/$tag"
done
# More functions
@ -230,9 +227,9 @@ conf_which() {
# Stop any running instances of wmiirc
echo Start wmiirc | wmiir write /event || exit 1
wmiir read /event |
while read event; do
wmiir read /event | while read event; do
set -- $event
event=$1; shift
Event_$event $@
done 2>/dev/null

View File

@ -15,10 +15,49 @@ status=$?
base=$(echo $BASE | sed 's/,/\\,/g')
re='\([^[:space:]/]*\..:[0-9]\)'
undup() { # GCC is crap.
awk '
function shift() {
for(n=1; n<=3; n++)
if(2*n <= nl)
for(i=1; i<=n; i++) {
if(l[i] != l[i+n])
break;
if(i == n) {
for(i=1; i<=n; i++)
print l[i]
nl -= 2*n;
for(i=1; i<=nl; i++)
l[i] = l[i+2*n];
return;
}
}
if(nl == 0)
return
print l[1]
for(i=1; i<nl; i++)
l[i] = l[i+1]
nl--
}
BEGIN{
nl=0
maxl=6
}
{
if(nl == maxl)
shift()
l[++nl] = $0
}
END{
while(nl > 0)
shift();
}'
}
cat $xtmp | sed "s,^$re,$base&,g; s,\([[:space:]]\)$re,\1$base\2,g" |
egrep -v ': error: .Each undeclared identifier|: error: for each function it appears|is dangerous, better use|is almost always misused|: In function |: At top level:|support .long long.|use of C99 long long|ISO C forbids conversion' |
sed 's/ .first use in this function.$//; s/\"\([^\"][^\"]*\)\", line \([0-9][0-9]*\)/\1:\2/g' |
uniq 1>&2
undup 1>&2
rm -f $xtmp
exit $status