removing container, not finished yet, fixed a bunch of other nasty bugs reported so far

This commit is contained in:
garbeam 2005-12-16 03:59:27 +02:00
parent eb09a51b8b
commit 8ece4071ae
15 changed files with 766 additions and 895 deletions

View File

@ -9,84 +9,55 @@
#include "wm.h"
static void handle_after_write_area(IXPServer * s, File * f);
static void handle_after_write_area(IXPServer *s, File *file);
Area *alloc_area(Page *p, char *layout)
{
char buf[MAX_BUF];
Area *a = (Area *) cext_emallocz(sizeof(Area));
size_t id = cext_sizeof_container(&p->areas);
a->page = p;
snprintf(buf, MAX_BUF, "/%s/layout/%d", p->file[P_PREFIX]->name, id);
snprintf(buf, MAX_BUF, "/%s/layout/%s", p->file[P_PREFIX]->name, layout);
a->file[A_PREFIX] = ixp_create(ixps, buf);
snprintf(buf, MAX_BUF, "/%s/layout/%d/frame", p->file[P_PREFIX]->name, id);
snprintf(buf, MAX_BUF, "/%s/layout/%s/frame", p->file[P_PREFIX]->name, layout);
a->file[A_FRAME_PREFIX] = ixp_create(ixps, buf);
snprintf(buf, MAX_BUF, "/%s/layout/%d/frame/sel", p->file[P_PREFIX]->name, id);
snprintf(buf, MAX_BUF, "/%s/layout/%s/frame/sel", p->file[P_PREFIX]->name, layout);
a->file[A_SEL_FRAME] = ixp_create(ixps, buf);
a->file[A_SEL_FRAME]->bind = 1;
snprintf(buf, MAX_BUF, "/%s/layout/%d/ctl", p->file[P_PREFIX]->name, id);
snprintf(buf, MAX_BUF, "/%s/layout/%s/ctl", p->file[P_PREFIX]->name, layout);
a->file[A_CTL] = ixp_create(ixps, buf);
a->file[A_CTL]->after_write = handle_after_write_area;
snprintf(buf, MAX_BUF, "/%s/layout/%d/name", p->file[P_PREFIX]->name, id);
snprintf(buf, MAX_BUF, "/%s/layout/%s/name", p->file[P_PREFIX]->name, layout);
a->file[A_LAYOUT] = wmii_create_ixpfile(ixps, buf, layout);
a->file[A_LAYOUT]->after_write = handle_after_write_area;
a->layout = get_layout(layout);
a->layout->init(a);
cext_attach_item(&p->areas, a);
cext_attach_item(areas, a);
a->layout = match_layout(layout);
a->layout->init(a, nil);
p->file[P_SEL_AREA]->content = a->file[A_PREFIX]->content;
return a;
}
void destroy_area(Area *a)
{
Client *c;
a->layout->deinit(a);
while ((c = cext_stack_get_top_item(&a->clients))) {
cext_detach_item(&a->clients, c);
cext_attach_item(detached, c);
}
ixp_remove_file(ixps, a->file[A_PREFIX]);
cext_detach_item(areas, a);
free(a);
}
void sel_area(Area *a)
{
Page *p = a->page;
Frame *f;
cext_stack_top_item(&p->areas, a);
p->file[P_SEL_AREA]->content = a->file[A_PREFIX]->content;
if ((f = get_sel_frame_of_area(a)))
a->layout->select(f, False);
}
static void iter_hide_area(void *item, void *aux)
{
XUnmapWindow(dpy, ((Frame *)item)->win);
}
void hide_area(Area * a)
{
cext_list_iterate(a->layout->get_frames(a), nil, iter_hide_area);
Frame *f;
for (f = a->layout->frames(a); f; f = f->next)
XUnmapWindow(dpy, f->win);
}
static void iter_show_area(void *item, void *aux)
void show_area(Area *a, Bool raise)
{
XMapWindow(dpy, ((Frame *)item)->win);
}
void show_area(Area * a)
{
cext_list_iterate(a->layout->get_frames(a), nil, iter_show_area);
}
Area *get_sel_area()
{
Page *p = get_sel_page();
return p ? cext_stack_get_top_item(&p->areas) : nil;
Frame *f;
for (f = a->layout->frames(a); f; f = f->next)
if (raise)
XMapRaised(dpy, f->win);
else
XMapWindow(dpy, f->win);
}
void attach_frame_to_area(Area *a, Frame *f)
@ -101,29 +72,25 @@ void detach_frame_from_area(Frame *f) {
f->area = 0;
}
static void iter_after_write_area(void *item, void *aux)
{
Area *a = item;
File *file = aux;
if (file == a->file[A_CTL]) {
run_action(file, a, a->layout->get_actions(a));
return;
}
if (file == a->file[A_LAYOUT]) {
Layout *l = get_layout(file->content);
if (l) {
a->layout->deinit(a);
a->layout = l;
a->layout->init(a);
invoke_wm_event(def[WM_EVENT_PAGE_UPDATE]);
static void handle_after_write_area(IXPServer *s, File *file) {
Page *p;
for (p = pages; p; p = p->next) {
if (file == p->managed->file[A_CTL]) {
run_action(file, p->managed, p->managed->layout->actions(p->managed));
return;
}
else if (file == p->floating->file[A_CTL]) {
run_action(file, p->floating, p->floating->layout->actions(p->floating));
return;
}
else if (file == p->managed->file[A_LAYOUT]) {
Layout *l = match_layout(file->content);
if (l) {
Client *clients = p->managed->layout->deinit(p->managed);
p->managed->layout = l;
p->managed->layout->init(p->managed, clients);
invoke_wm_event(def[WM_EVENT_PAGE_UPDATE]);
}
}
return;
}
}
static void handle_after_write_area(IXPServer *s, File *f) {
cext_list_iterate(areas, f, iter_after_write_area);
}

View File

@ -25,16 +25,15 @@ Client *alloc_client(Window w)
c->file[C_NAME] = wmii_create_ixpfile(ixps, buf, (char *)name.value);
free(name.value);
id++;
cext_attach_item(clients, c);
return c;
}
void sel_client(Client * c)
void focus_client(Client * c)
{
Frame *f = 0;
/* sel client */
f = c->frame;
cext_stack_top_item(&f->clients, c);
f->sel = c;
f->file[F_SEL_CLIENT]->content = c->file[C_PREFIX]->content;
XRaiseWindow(dpy, c->win);
XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
@ -161,7 +160,7 @@ void handle_client_property(Client *c, XPropertyEvent *e)
}
free(name.value);
if (c->frame)
draw_client(c, nil);
draw_client(c);
invoke_wm_event(def[WM_EVENT_CLIENT_UPDATE]);
break;
case XA_WM_TRANSIENT_FOR:
@ -178,43 +177,38 @@ void handle_client_property(Client *c, XPropertyEvent *e)
void destroy_client(Client * c)
{
cext_detach_item(detached, c);
cext_detach_item(clients, c);
detach_detached(c);
ixp_remove_file(ixps, c->file[C_PREFIX]);
free(c);
}
/* speed reasoned function for client property change */
void draw_client(void *item, void *aux)
void draw_client(Client *client)
{
Client *c = item;
Frame *f = c->frame;
unsigned int tw, tabh = tab_height(f);
size_t size;
int i;
Frame *f = client->frame;
unsigned int i = 0, tw, tabh = tab_height(f);
Draw d = { 0 };
Client *c;
if (!tabh)
return;
size = cext_sizeof_container(&f->clients);
tw = f->rect.width;
if (size)
tw /= size;
i = cext_list_get_item_index(&f->clients, c);
tw = f->rect.width / f->nclients;
for (c = f->clients; c && c != client; c = c->next)
i++;
d.drawable = f->win;
d.gc = f->gc;
d.rect.x = i * tw;
d.rect.y = 0;
d.rect.width = tw;
if (i && (i == size - 1))
if (i && (i == f->nclients - 1))
d.rect.width = f->rect.width - d.rect.x;
d.rect.height = tabh;
d.data = c->file[C_NAME]->content;
d.font = font;
if ((f == get_sel_frame()) && (c == get_sel_client())) {
if ((f == sel_frame()) && (c == f->sel)) {
d.bg = blitz_loadcolor(dpy, screen_num, f->file[F_SEL_BG_COLOR]->content);
d.fg = blitz_loadcolor(dpy, screen_num, f->file[F_SEL_FG_COLOR]->content);
d.border = blitz_loadcolor(dpy, screen_num, f->file[F_SEL_BORDER_COLOR]->content);
@ -229,7 +223,9 @@ void draw_client(void *item, void *aux)
void draw_clients(Frame * f)
{
cext_list_iterate(&f->clients, 0, draw_client);
Client *c;
for (c = f->clients; c; c = c->next)
draw_client(c);
}
void gravitate(Client * c, unsigned int tabh, unsigned int bw, int invert)
@ -295,36 +291,66 @@ void gravitate(Client * c, unsigned int tabh, unsigned int bw, int invert)
void attach_client(Client * c)
{
Area *a = 0;
if (!cext_sizeof_container(pages))
alloc_page();
Page *p = pages;
if (!p)
p = alloc_page();
/* transient stuff */
a = get_sel_area();
a = p->sel;
if (c && c->trans) {
Client *t = win_to_client(c->trans);
if (t && t->frame)
a = cext_list_get_item(&t->frame->area->page->areas, 0);
a = p->floating;
}
cext_attach_item(&a->clients, c);
a->layout->attach(a, c);
invoke_wm_event(def[WM_EVENT_PAGE_UPDATE]);
}
void detach_client(Client *c, Bool unmap) {
Page *p;
Frame *f = c->frame;
Area *a = f ? f->area : nil;
if (a) {
a->layout->detach(a, c, unmap);
cext_detach_item(&a->clients, c);
}
if (c->destroyed)
destroy_client(c);
if ((p = get_sel_page()))
sel_page(p);
if (selpage)
focus_page(selpage);
}
Client *get_sel_client()
Client *sel_client()
{
Frame *f = get_sel_frame();
return f ? cext_stack_get_top_item(&f->clients) : nil;
Frame *f = sel_frame();
return f ? f->sel : nil;
}
Client *clientat(Client *clients, size_t idx)
{
size_t i = 0;
Client *c = clients;
for (; c && i != idx ; c = c->next) i++;
return c;
}
void detach_detached(Client *c)
{
if (detached == c) {
if (c->next)
c->next->prev = nil;
detached = c->next;
}
else {
if (c->next)
c->next->prev = c->prev;
c->prev->next = c->next;
}
ndetached--;
}
void attach_detached(Client *c)
{
c->prev = nil;
c->next = detached;
if (detached)
detached->prev = c;
detached = c;
}

View File

@ -116,10 +116,9 @@ static void handle_configurerequest(XEvent * e)
if (f) {
Page *p = f->area->page;
if (cext_list_get_item_index(&p->areas, f->area)) {
Area *a = cext_list_get_item(&p->areas, 0);
if (f->area == p->managed) {
f->area->layout->detach(f->area, c, False);
a->layout->attach(a, c);
p->floating->layout->attach(p->floating, c);
f = c->frame;
}
bw = border_width(f);
@ -274,7 +273,7 @@ static void handle_enternotify(XEvent * e)
c = win_to_client(ev->window);
if (c && c->frame) {
sel_area(c->frame->area);
c->frame->area->layout->select(c->frame, False);
c->frame->area->layout->focus(c->frame, False);
}
}

View File

@ -11,8 +11,8 @@
#include "wm.h"
static void select_client(void *obj, char *arg);
static void handle_after_write_frame(IXPServer * s, File * f);
static void handle_before_read_frame(IXPServer * s, File * f);
static void handle_after_write_frame(IXPServer *s, File *file);
static void handle_before_read_frame(IXPServer *s, File *file);
/* action table for /frame/?/ namespace */
Action frame_acttbl[] = {
@ -93,26 +93,26 @@ Frame *alloc_frame(XRectangle * r)
XDefineCursor(dpy, f->win, f->cursor);
f->gc = XCreateGC(dpy, f->win, 0, 0);
XSync(dpy, False);
cext_attach_item(frames, f);
return f;
}
static int comp_frame_win(void *pattern, void *frame)
{
Window w = *(Window *)pattern;
Frame *f = frame;
return w == f->win;
}
Frame *win_to_frame(Window w)
{
return cext_find_item(frames, &w, comp_frame_win);
Page *p;
for (p = pages; p; p = p->next) {
Frame *f;
for (f = p->managed->layout->frames(p->managed); f; f = f->next)
if (f->win == w)
return f;
for (f = p->floating->layout->frames(p->floating); f; f = f->next)
if (f->win == w)
return f;
}
return nil;
}
void destroy_frame(Frame * f)
{
cext_detach_item(frames, f);
XFreeGC(dpy, f->gc);
XDestroyWindow(dpy, f->win);
ixp_remove_file(ixps, f->file[F_PREFIX]);
@ -133,32 +133,9 @@ unsigned int border_width(Frame * f)
return 0;
}
typedef struct {
unsigned int tabh;
unsigned int bw;
} Twouint;
static void iter_resize_client(void *item, void *aux)
{
Client *c = item;
Twouint *v = aux;
c->rect.x = v->bw;
c->rect.y = v->tabh ? v->tabh : v->bw;
c->rect.width = c->frame->rect.width - 2 * v->bw;
c->rect.height = c->frame->rect.height - v->bw - (v->tabh ? v->tabh : v->bw);
XMoveResizeWindow(dpy, c->win, c->rect.x, c->rect.y, c->rect.width, c->rect.height);
configure_client(c);
}
static void resize_clients(Frame * f, int tabh, int bw)
{
Twouint aux = { tabh, bw };
cext_list_iterate(&f->clients, &aux, iter_resize_client);
}
static void check_dimensions(Frame * f, unsigned int tabh, unsigned int bw)
{
Client *c = get_sel_client();
Client *c = sel_client();
if (!c)
return;
@ -182,7 +159,7 @@ static void check_dimensions(Frame * f, unsigned int tabh, unsigned int bw)
static void resize_incremental(Frame * f, unsigned int tabh, unsigned int bw)
{
Client *c = get_sel_client();
Client *c = f->sel;
if (!c)
return;
/* increment stuff, see chapter 4.1.2.3 of the ICCCM Manual */
@ -211,6 +188,7 @@ void resize_frame(Frame * f, XRectangle * r, XPoint * pt)
Area *a = f->area;
unsigned int tabh = tab_height(f);
unsigned int bw = border_width(f);
Client *c;
a->layout->resize(f, r, pt);
@ -221,7 +199,15 @@ void resize_frame(Frame * f, XRectangle * r, XPoint * pt)
resize_incremental(f, tabh, bw);
XMoveResizeWindow(dpy, f->win, f->rect.x, f->rect.y, f->rect.width, f->rect.height);
resize_clients(f, (tabh ? tabh : bw), bw);
for (c = f->clients; c; c = c->next) {
c->rect.x = bw;
c->rect.y = tabh ? tabh : bw;
c->rect.width = c->frame->rect.width - 2 * bw;
c->rect.height = c->frame->rect.height - bw - (tabh ? tabh : bw);
XMoveResizeWindow(dpy, c->win, c->rect.x, c->rect.y, c->rect.width, c->rect.height);
configure_client(c);
}
}
/**
@ -253,7 +239,7 @@ void draw_frame(Frame *f)
d.gc = f->gc;
/* define ground plate (i = 0) */
if (f == get_sel_frame()) {
if (f == sel_frame()) {
d.bg = blitz_loadcolor(dpy, screen_num, f->file[F_SEL_BG_COLOR]->content);
d.fg = blitz_loadcolor(dpy, screen_num, f->file[F_SEL_FG_COLOR]->content);
d.border = blitz_loadcolor(dpy, screen_num, f->file[F_SEL_BORDER_COLOR]->content);
@ -275,59 +261,88 @@ void draw_frame(Frame *f)
void handle_frame_buttonpress(XButtonEvent *e, Frame *f)
{
Align align;
size_t size = cext_sizeof_container(&f->clients);
int bindex, cindex = e->x / (f->rect.width / size);
/*fprintf(stderr, "%d (x) / %d (w) / %d (size) = %d (#c)\n", e->x, f->rect.width, size, cindex);*/
/*sel_client(cext_list_get_item(&f->clients, cindex));*/
cext_stack_top_item(&f->clients, cext_list_get_item(&f->clients, cindex));
int bindex, cindex = e->x / (f->rect.width / f->nclients);
f->sel = clientat(f->clients, cindex);
if (e->button == Button1) {
align = cursor_to_align(f->cursor);
if (align == CENTER)
mouse_move(f);
else
mouse_resize(f, align);
f->area->layout->select(f, False);
f->area->layout->focus(f, False);
return;
}
f->area->layout->select(f, False);
f->area->layout->focus(f, False);
bindex = F_EVENT_B2PRESS - 2 + e->button;
/* frame mouse handling */
if (f->file[bindex]->content)
wmii_spawn(dpy, f->file[bindex]->content);
}
void attach_client_to_frame(Frame *f, Client *c)
void attach_client_to_frame(Frame *f, Client *client)
{
Client *c;
wmii_move_ixpfile(c->file[C_PREFIX], f->file[F_CLIENT_PREFIX]);
f->file[F_SEL_CLIENT]->content = c->file[C_PREFIX]->content;
cext_attach_item(&f->clients, c);
c->frame = f;
f->file[F_SEL_CLIENT]->content = client->file[C_PREFIX]->content;
for (c = f->clients; c && c->next; c = c->next);
if (!c) {
f->clients = client;
client->prev = client->next = nil;
}
else {
client->prev = c;
client->next = nil;
c->next = client;
}
f->sel = client;
client->frame = f;
resize_frame(f, &f->rect, 0);
reparent_client(c, f->win, c->rect.x, c->rect.y);
show_client(c);
sel_client(c);
reparent_client(client, f->win, client->rect.x, client->rect.y);
show_client(client);
sel_client(client);
}
void detach_client_from_frame(Client *c, Bool unmap)
{
Frame *f = c->frame;
Client *client;
c->frame = nil;
f->file[F_SEL_CLIENT]->content = nil;
wmii_move_ixpfile(c->file[C_PREFIX], def[WM_DETACHED_CLIENT]);
cext_detach_item(&f->clients, c);
if (f->sel == c) {
if (c->prev)
f->sel = c->prev;
else
f->sel = nil;
}
if (f->clients == c) {
if (c->next)
c->next->prev = nil;
f->clients = c->next;
}
else {
c->prev->next = c->next;
if (c->next)
c->next->prev = c->prev;
}
if (!f->sel)
f->sel = f->clients;
if (!c->destroyed) {
if (!unmap) {
cext_attach_item(detached, c);
attach_detached(c);
hide_client(c);
}
c->rect.x = f->rect.x;
c->rect.y = f->rect.y;
reparent_client(c, root, c->rect.x, c->rect.y);
}
if ((client = cext_stack_get_top_item(&f->clients))) {
sel_client(client);
f->area->layout->select(f, False);
if (f->sel) {
focus_client(f->sel);
f->area->layout->focus(f, False);
}
}
@ -335,74 +350,89 @@ static void select_client(void *obj, char *arg)
{
Client *c;
Frame *f = obj;
size_t size = cext_sizeof_container(&f->clients);
if (!f || !arg || size == 1)
if (!f || !arg || !f->clients->next)
return;
c = cext_stack_get_top_item(&f->clients);
if (!strncmp(arg, "prev", 5))
c = cext_list_get_prev_item(&f->clients, c);
c = f->sel->prev;
else if (!strncmp(arg, "next", 5))
c = cext_list_get_next_item(&f->clients, c);
c = f->sel->next;
else
c = cext_list_get_item(&f->clients, blitz_strtonum(arg, 0, cext_sizeof_container(&f->clients) - 1));
sel_client(c);
f->area->layout->select(f, False);
c = clientat(f->clients, blitz_strtonum(arg, 0, f->nclients - 1));
focus_client(c);
f->area->layout->focus(f, False);
}
static void iter_before_read_frame(void *item, void *aux)
static Frame *handle_before_read_frames(IXPServer *s, File *file, Area *a)
{
Frame *f = item;
File *file = aux;
if (file == f->file[F_GEOMETRY]) {
char buf[64];
snprintf(buf, 64, "%d,%d,%d,%d", f->rect.x, f->rect.y, f->rect.width, f->rect.height);
if (file->content)
free(file->content);
file->content = cext_estrdup(buf);
file->size = strlen(buf);
Frame *f;
char buf[64];
for (f = a->layout->frames(a); f; f = f->next)
if (file == f->file[F_GEOMETRY]) {
snprintf(buf, 64, "%d,%d,%d,%d", f->rect.x, f->rect.y, f->rect.width, f->rect.height);
if (file->content)
free(file->content);
file->content = cext_estrdup(buf);
file->size = strlen(buf);
return f;
}
return nil;
}
static void handle_before_read_frame(IXPServer *s, File *file)
{
Page *p;
for (p = pages; p; p = p->next) {
if (handle_before_read_frames(s, file, p->managed)
|| handle_before_read_frames(s, file, p->floating))
return;
}
}
static void handle_before_read_frame(IXPServer *s, File *f)
static Frame *handle_after_write_frames(IXPServer *s, File *file, Area *a)
{
cext_list_iterate(frames, f, iter_before_read_frame);
}
static void iter_after_write_frame(void *item, void *aux)
{
Frame *f = item;
File *file = aux;
if (file == f->file[F_CTL]) {
run_action(file, f, frame_acttbl);
return;
}
if (file == f->file[F_TAB] || file == f->file[F_BORDER] || file == f->file[F_HANDLE_INC]) {
f->area->layout->arrange(f->area);
return;
} else if (file == f->file[F_GEOMETRY]) {
char *geom = f->file[F_GEOMETRY]->content;
if (geom && strrchr(geom, ',')) {
XRectangle frect = f->rect;
blitz_strtorect(&rect, &frect, geom);
resize_frame(f, &frect, 0);
Frame *f;
for (f = a->layout->frames(a); f; f = f->next) {
if (file == f->file[F_CTL]) {
run_action(file, f, frame_acttbl);
return f;
}
if (file == f->file[F_TAB] || file == f->file[F_BORDER] || file == f->file[F_HANDLE_INC]) {
f->area->layout->arrange(f->area);
return f;
} else if (file == f->file[F_GEOMETRY]) {
char *geom = f->file[F_GEOMETRY]->content;
if (geom && strrchr(geom, ',')) {
XRectangle frect = f->rect;
blitz_strtorect(&rect, &frect, geom);
resize_frame(f, &frect, 0);
}
return f;
}
}
return nil;
}
static void handle_after_write_frame(IXPServer * s, File * f)
static void handle_after_write_frame(IXPServer *s, File *file)
{
cext_list_iterate(frames, f, iter_after_write_frame);
Page *p;
for (p = pages; p; p = p->next) {
if (handle_after_write_frames(s, file, p->managed)
|| handle_after_write_frames(s, file, p->floating))
return;
}
}
Frame *get_sel_frame_of_area(Area *a)
Frame *sel_frame()
{
return cext_stack_get_top_item(a->layout->get_frames(a));
}
Frame *get_sel_frame()
{
Page *p = get_sel_page();
if (!p)
Area *a = sel_area();
if (!a)
return nil;
return get_sel_frame_of_area(get_sel_area(p));
return a->layout->sel(a);
}
Frame *get_bottom_frame(Frame *frames)
{
Frame *f;
for (f = frames; f && f->next; f = f->next);
return f;
}

View File

@ -7,15 +7,11 @@
#include "wm.h"
static int comp_layout_name(void *name, void *layout)
Layout *match_layout(char *name)
{
Layout *l = layout;
size_t len = strlen(l->name);
return !strncmp(name, l->name, len);
}
Layout *get_layout(char *name)
{
return cext_find_item(layouts, name, comp_layout_name);
Layout *l;
for (l = layouts; l; l = l->next)
if (!strncmp(name, l->name, strlen(l->name)))
return l;
return nil;
}

View File

@ -12,26 +12,42 @@
typedef struct Acme Acme;
typedef struct Column Column;
typedef struct ColFrame ColFrame;
struct Acme {
Container columns;
Container frames;
Column *sel;
Column *columns;
size_t ncolumns;
Frame *frames;
size_t nframes;
};
struct ColFrame {
Frame *frame;
ColFrame *next;
ColFrame *prev;
Column *col;
};
struct Column {
Container frames;
ColFrame *sel;
ColFrame *frames;
size_t nframes;
XRectangle rect;
Column *prev;
Column *next;
};
static void init_col(Area * a);
static void deinit_col(Area * a);
static void arrange_col(Area * a);
static Bool attach_col(Area * a, Client * c);
static void detach_col(Area * a, Client * c, Bool unmap);
static void resize_col(Frame *f, XRectangle * new, XPoint * pt);
static void select_col(Frame *f, Bool raise);
static Container *get_frames_col(Area *a);
static Action *get_actions_col(Area *a);
static void init_col(Area *a, Client *clients);
static Client *deinit_col(Area *a);
static void arrange_col(Area *a);
static Bool attach_col(Area *a, Client *c);
static void detach_col(Area *a, Client *c, Bool unmap);
static void resize_col(Frame *f, XRectangle *new, XPoint *pt);
static void focus_col(Frame *f, Bool raise);
static Frame *frames_col(Area *a);
static Frame *sel_col(Area *a);
static Action *actions_col(Area *a);
static void select_frame(void *obj, char *arg);
static void swap_frame(void *obj, char *arg);
@ -44,98 +60,176 @@ static Action lcol_acttbl[] = {
{0, 0}
};
static Layout lcol = { "col", init_col, deinit_col, arrange_col, attach_col, detach_col,
resize_col, select_col, get_frames_col, get_actions_col };
void init_layout_column()
{
cext_attach_item(layouts, &lcol);
}
Layout *lp, *l = cext_emallocz(sizeof(Layout));
l->name = "column";
l->init = init_col;
l->deinit = deinit_col;
l->arrange = arrange_col;
l->attach = attach_col;
l->detach = detach_col;
l->resize = resize_col;
l->focus = focus_col;
l->frames = frames_col;
l->sel = sel_col;
l->actions = actions_col;
static Column *get_sel_column(Acme *acme)
{
return cext_stack_get_top_item(&acme->columns);
}
static void iter_arrange_column_frame(void *frame, void *height)
{
Frame *f = frame;
Column *col = f->aux;
size_t size = cext_sizeof_container(&col->frames);
unsigned int h = *(unsigned int *)height;
int idx = cext_list_get_item_index(&col->frames, f) ;
f->rect = col->rect;
f->rect.y = area_rect.y + idx * h;
if (idx + 1 == size)
f->rect.height = area_rect.height - f->rect.y + area_rect.y;
for (lp = layouts; lp && lp->next; lp = lp->next);
if (lp)
lp->next = l;
else
f->rect.height = h;
resize_frame(f, &f->rect, 0);
layouts = l;
}
static void iter_arrange_column(void *column, void *area)
static void arrange_column(Column *col)
{
Column *col = column;
size_t size = cext_sizeof_container(&col->frames);
unsigned int height;
if (size) {
height= area_rect.height / size;
cext_list_iterate(&col->frames, &height, iter_arrange_column_frame);
ColFrame *cf;
unsigned int i = 0, h = area_rect.height / col->nframes;
for (cf = col->frames; cf; cf = cf->next) {
Frame *f = cf->frame;
f->rect = col->rect;
f->rect.y = area_rect.y + i * h;
if (!cf->next)
f->rect.height = area_rect.height - f->rect.y + area_rect.y;
else
f->rect.height = h;
resize_frame(f, &f->rect, 0);
i++;
}
}
static void arrange_col(Area *a)
{
Acme *acme = a->aux;
cext_list_iterate(&acme->columns, a, iter_arrange_column);
Column *col;
for (col = acme->columns; col; col = col->next)
arrange_column(col);
XSync(dpy, False);
}
static void iter_attach_col(void *client, void *area)
static void init_col(Area *a, Client *clients)
{
attach_col(area, client);
Client *n, *c = clients;
a->aux = cext_emallocz(sizeof(Acme));
while (c) {
n = c->next;
attach_col(a, c);
c = n;
}
}
static void init_col(Area *a)
{
Acme *acme = cext_emallocz(sizeof(Acme));
a->aux = acme;
cext_list_iterate(&a->clients, a, iter_attach_col);
}
static void iter_detach_client(void *client, void *area)
{
Area *a = area;
detach_col(a, (Client *)client, a->page != get_sel_page());
}
static void deinit_col(Area *a)
static void attach_frame(Area *a, Column *col, Frame *f)
{
Acme *acme = a->aux;
Column *col;
cext_list_iterate(&a->clients, a, iter_detach_client);
while ((col = get_sel_column(acme)))
{
cext_detach_item(&acme->columns, col);
ColFrame *c, *cf = cext_emallocz(sizeof(ColFrame));
Frame *fr;
cf->frame = f;
cf->col = col;
f->aux = cf;
for (c = col->frames; c && c->next; c = c->next);
if (!c)
col->frames = cf;
else {
c->next = cf;
cf->prev = c;
}
col->sel = cf;
col->nframes++;
for (fr = acme->frames; fr && fr->next; fr = fr->next);
if (!fr)
acme->frames = f;
else {
fr->next = f;
f->prev = fr;
}
attach_frame_to_area(a, f);
acme->nframes++;
}
static void detach_frame(Area *a, Frame *f)
{
Acme *acme = a->aux;
ColFrame *cf = f->aux;
Column *col = cf->col;
if (col->sel == cf) {
if (cf->prev)
col->sel = cf->prev;
else
col->sel = nil;
}
if (cf->prev)
cf->prev->next = cf->next;
else
col->frames = cf->next;
if (cf->next)
cf->next->prev = cf->prev;
if (!col->sel)
col->sel = col->frames;
free(cf);
col->nframes--;
if (f->prev)
f->prev->next = f->next;
else
acme->frames = f->next;
if (f->next)
f->next->prev = f->prev;
f->aux = nil;
detach_frame_from_area(f);
acme->nframes--;
}
static Client *deinit_col(Area *a)
{
Acme *acme = a->aux;
Frame *f;
Client *cl, *res = nil, *c = nil;
Column *col = acme->columns;
while ((f = acme->frames)) {
while ((cl = f->clients)) {
detach_client_from_frame(cl, False);
cl->prev = cl->next = 0;
if (!c)
res = c = cl;
else {
c->next = cl;
cl->prev = c;
c = cl;
}
}
detach_frame(a, f);
destroy_frame(f);
}
while ((col = acme->columns)) {
acme->columns = col->next;
free(col);
}
free(acme);
a->aux = 0;
return res;
}
static Bool attach_col(Area *a, Client *c)
{
Acme *acme = a->aux;
Column *col = get_sel_column(acme);
Frame *f = get_sel_frame_of_area(a);
Column *col = acme->sel;
Frame *f = nil;
if (col && col->sel)
f = col->sel->frame;
if (!col) {
col = cext_emallocz(sizeof(Column));
col->rect = area_rect;
cext_attach_item(&acme->columns, col);
acme->columns = acme->sel = col;
acme->ncolumns++;
}
/* check for tabbing? */
@ -143,34 +237,31 @@ static Bool attach_col(Area *a, Client *c)
f = 0;
if (!f) {
f = alloc_frame(&c->rect);
attach_frame_to_area(a, f);
f->aux = col;
cext_attach_item(&acme->frames, f);
cext_attach_item(&col->frames, f);
attach_frame(a, col, f);
}
attach_client_to_frame(f, c);
iter_arrange_column(col, a);
if (a->page == get_sel_page())
arrange_column(col);
if (a->page == selpage)
XMapWindow(dpy, f->win);
select_col(f, True);
focus_col(f, True);
return True;
}
static void update_column_width(Area *a)
{
Acme *acme = a->aux;
size_t size = cext_sizeof_container(&acme->columns);
unsigned int i, width;
unsigned int i = 0, width;
Column *col;
if (!size)
if (!acme->ncolumns)
return;
width = area_rect.width / size;
for (i = 0; i < size; i++) {
Column *col = cext_list_get_item(&acme->columns, i);
width = area_rect.width / acme->ncolumns;
for (col = acme->columns; col; col = col->next) {
col->rect = area_rect;
col->rect.x = i * width;
col->rect.width = width;
i++;
}
arrange_col(a);
}
@ -182,128 +273,121 @@ static void detach_col(Area *a, Client *c, Bool unmap)
Column *col = f->aux;
detach_client_from_frame(c, unmap);
if (!cext_sizeof_container(&f->clients)) {
detach_frame_from_area(f);
cext_detach_item(&acme->frames, f);
cext_detach_item(&col->frames, f);
if (!f->clients) {
detach_frame(a, f);
destroy_frame(f);
}
else return;
if (cext_sizeof_container(&col->frames))
iter_arrange_column(col, a);
if (col->frames)
arrange_column(col);
else {
cext_detach_item(&acme->columns, col);
if (acme->sel == col) {
if (col->prev)
acme->sel = col->prev;
else
acme->sel = nil;
}
if (col->prev)
col->prev->next = col->next;
else
acme->columns = col->next;
if (col->next)
col->next->prev = col->prev;
if (!acme->sel)
acme->sel = acme->columns;
acme->ncolumns--;
free(col);
update_column_width(a);
}
}
static void iter_match_frame_horiz(void *frame, void *rect)
static void match_frame_horiz(Column *col, XRectangle *r)
{
Frame *f = frame;
XRectangle *r = rect;
f->rect.x = r->x;
f->rect.width = r->width;
resize_frame(f, &f->rect, nil);
ColFrame *cf;
for (cf = col->frames; cf; cf = cf->next) {
Frame *f = cf->frame;
f->rect.x = r->x;
f->rect.width = r->width;
resize_frame(f, &f->rect, nil);
}
}
static void drop_resize(Frame *f, XRectangle *new)
{
Column *west = 0, *east = 0, *col = f->aux;
Frame *north = 0, *south = 0;
Acme *acme = f->area->aux;
size_t ncol = cext_sizeof_container(&acme->columns);
size_t nfr = cext_sizeof_container(&col->frames);
int colidx = cext_list_get_item_index(&acme->columns, col);
int fidx = cext_list_get_item_index(&col->frames, f);
ColFrame *north = 0, *south = 0;
ColFrame *cf = f->aux;
if (colidx > 0)
west = cext_list_get_item(&acme->columns, colidx - 1);
if (colidx + 1 < ncol)
east = cext_list_get_item(&acme->columns, colidx + 1);
if (fidx > 0)
north = cext_list_get_item(&col->frames, fidx - 1);
if (fidx + 1 < nfr)
south = cext_list_get_item(&col->frames, fidx + 1);
west = col->prev;
east = col->next;
north = cf->prev;
south = cf->next;
/* horizontal resize */
if (west && (new->x != f->rect.x)) {
west->rect.width = new->x - west->rect.x;
col->rect.width += f->rect.x - new->x;
col->rect.x = new->x;
cext_list_iterate(&west->frames, &west->rect, iter_match_frame_horiz);
cext_list_iterate(&col->frames, &col->rect, iter_match_frame_horiz);
match_frame_horiz(west, &west->rect);
match_frame_horiz(col, &col->rect);
}
if (east && (new->x + new->width != f->rect.x + f->rect.width)) {
east->rect.width -= new->x + new->width - east->rect.x;
east->rect.x = new->x + new->width;
col->rect.x = new->x;
col->rect.width = new->width;
cext_list_iterate(&col->frames, &col->rect, iter_match_frame_horiz);
cext_list_iterate(&east->frames, &east->rect, iter_match_frame_horiz);
match_frame_horiz(col, &col->rect);
match_frame_horiz(east, &east->rect);
}
/* vertical resize */
if (north && (new->y != f->rect.y)) {
north->rect.height = new->y - north->rect.y;
north->frame->rect.height = new->y - north->frame->rect.y;
f->rect.height += f->rect.y - new->y;
f->rect.y = new->y;
resize_frame(north, &north->rect, nil);
resize_frame(north->frame, &north->frame->rect, nil);
resize_frame(f, &f->rect, nil);
}
if (south && (new->y + new->height != f->rect.y + f->rect.height)) {
south->rect.height -= new->y + new->height - south->rect.y;
south->rect.y = new->y + new->height;
south->frame->rect.height -= new->y + new->height - south->frame->rect.y;
south->frame->rect.y = new->y + new->height;
f->rect.y = new->y;
f->rect.height = new->height;
resize_frame(f, &f->rect, nil);
resize_frame(south, &south->rect, nil);
resize_frame(south->frame, &south->frame->rect, nil);
}
}
static int comp_pointer_frame(void *point, void *frame)
{
Frame *f = frame;
XPoint *pt = point;
fprintf(stderr, "frame: %d,%d in %d,%d,%d,%d ?\n", pt->x, pt->y, f->rect.x, f->rect.y, f->rect.width, f->rect.height);
return blitz_ispointinrect(pt->x, pt->y, &f->rect);
}
static int comp_pointer_col(void *point, void *column)
{
Column *col = column;
XPoint *pt = point;
fprintf(stderr, "col: %d,%d in %d,%d,%d,%d ?\n", pt->x, pt->y, col->rect.x, col->rect.y, col->rect.width, col->rect.height);
return blitz_ispointinrect(pt->x, pt->y, &col->rect);
}
static void drop_moving(Frame *f, XRectangle *new, XPoint *pt)
{
Acme *acme = f->area->aux;
Column *src = f->aux, *tgt = 0;
Area *a = f->area;
ColFrame *fcf = f->aux;
Column *src = fcf->col, *tgt = 0;
Acme *acme = a->aux;
if (!pt)
return;
if ((tgt = cext_find_item(&acme->columns, pt, comp_pointer_col))) {
for (tgt = acme->columns; tgt && !blitz_ispointinrect(pt->x, pt->y, &tgt->rect); tgt = tgt->next);
if (tgt) {
if (tgt != src) {
if (cext_sizeof_container(&src->frames) < 2)
if (src->nframes < 2)
return;
cext_detach_item(&src->frames, f);
cext_attach_item(&tgt->frames, f);
f->aux = tgt;
iter_arrange_column(tgt, f->area);
iter_arrange_column(src, f->area);
select_col(f, True);
detach_frame(a, f);
attach_frame(a, tgt, f);
arrange_column(src);
arrange_column(tgt);
focus_col(f, True);
}
else {
Frame *other = cext_find_item(&tgt->frames, pt, comp_pointer_frame);
if (other && other != f) {
cext_swap_items(&tgt->frames, f, other);
iter_arrange_column(tgt, f->area);
select_col(f, True);
ColFrame *cf;
for (cf = src->frames; cf && !blitz_ispointinrect(pt->x, pt->y, &cf->frame->rect); cf = cf->next);
if (cf && cf != fcf) {
Frame *tmp = cf->frame;
cf->frame = f;
fcf->frame = tmp;
arrange_column(src);
focus_col(f, True);
}
}
}
@ -318,32 +402,41 @@ static void resize_col(Frame *f, XRectangle *new, XPoint *pt)
drop_resize(f, new);
}
static void select_col(Frame *f, Bool raise)
static void focus_col(Frame *f, Bool raise)
{
Area *a = f->area;
Acme *acme = a->aux;
Column *col = f->aux;
Frame *old = get_sel_frame();
ColFrame *old, *fcf = f->aux;
Column *col = fcf->col;
cext_stack_top_item(&acme->columns, col);
sel_client(cext_stack_get_top_item(&f->clients));
cext_stack_top_item(&col->frames, f);
cext_stack_top_item(&acme->frames, f);
old = col->sel;
acme->sel = col;
col->sel = fcf;
sel_client(f->sel);
a->file[A_SEL_FRAME]->content = f->file[F_PREFIX]->content;
if (raise)
center_pointer(f);
if (old && old != f)
draw_frame(old);
if (old && old != fcf)
draw_frame(old->frame);
draw_frame(f);
}
static Container *get_frames_col(Area *a)
static Frame *frames_col(Area *a)
{
Acme *acme = a->aux;
return &acme->frames;
return acme->frames;
}
static Action *get_actions_col(Area *a)
static Frame *sel_col(Area *a) {
Acme *acme = a->aux;
Column *col = acme->sel;
if (col && col->sel)
return col->sel->frame;
return nil;
}
static Action *actions_col(Area *a)
{
return lcol_acttbl;
}
@ -381,7 +474,7 @@ static void select_frame(void *obj, char *arg)
}
else
f = cext_list_get_item(&col->frames, blitz_strtonum(arg, 0, cext_sizeof_container(&col->frames) - 1));
select_col(f, True);
focus_col(f, True);
}
static void swap_frame(void *obj, char *arg)
@ -423,7 +516,7 @@ static void swap_frame(void *obj, char *arg)
cext_swap_items(&col->frames, f, north);
resize_frame(f, &f->rect, nil);
resize_frame(north, &north->rect, nil);
select_col(f, True);
focus_col(f, True);
}
else if (!strncmp(arg, "south", 6) && south) {
r = south->rect;
@ -432,7 +525,7 @@ static void swap_frame(void *obj, char *arg)
cext_swap_items(&col->frames, f, south);
resize_frame(f, &f->rect, nil);
resize_frame(south, &south->rect, nil);
select_col(f, True);
focus_col(f, True);
}
else if (!strncmp(arg, "west", 5) && west && (ncol > 1)) {
Frame *other = cext_stack_get_top_item(&west->frames);
@ -447,7 +540,7 @@ static void swap_frame(void *obj, char *arg)
other->aux = col;
resize_frame(f, &f->rect, nil);
resize_frame(other, &other->rect, nil);
select_col(f, True);
focus_col(f, True);
}
else if (!strncmp(arg, "east", 5) && east && (ncol > 1)) {
Frame *other = cext_stack_get_top_item(&east->frames);
@ -462,7 +555,7 @@ static void swap_frame(void *obj, char *arg)
other->aux = col;
resize_frame(f, &f->rect, nil);
resize_frame(other, &other->rect, nil);
select_col(f, True);
focus_col(f, True);
}
}
@ -482,5 +575,6 @@ static void new_col(void *obj, char *arg)
cext_attach_item(&col->frames, f);
cext_attach_item(&acme->columns, col);
update_column_width(a);
select_col(f, True);
focus_col(f, True);
}

View File

@ -9,74 +9,90 @@
#include "wm.h"
static void handle_after_write_page(IXPServer * s, File * f);
static void handle_after_write_page(IXPServer *s, File *file);
static void select_area(void *obj, char *arg);
static void toggle_area(void *obj, char *arg);
/* action table for /?/ namespace */
Action page_acttbl[] = {
{"select", select_area},
{"toggle", toggle_area},
{0, 0}
};
Page *alloc_page()
{
Page *p = cext_emallocz(sizeof(Page));
Page *p, *new = cext_emallocz(sizeof(Page));
char buf[MAX_BUF], buf2[16];
size_t id = cext_sizeof_container(pages);
snprintf(buf2, sizeof(buf2), "%d", id);
snprintf(buf, sizeof(buf), "/%d", id);
p->file[P_PREFIX] = ixp_create(ixps, buf);
snprintf(buf, sizeof(buf), "/%d/name", id);
p->file[P_NAME] = wmii_create_ixpfile(ixps, buf, buf2);
snprintf(buf, sizeof(buf), "/%d/layout/", id);
p->file[P_AREA_PREFIX] = ixp_create(ixps, buf);
snprintf(buf, sizeof(buf), "/%d/layout/sel", id);
p->file[P_SEL_AREA] = ixp_create(ixps, buf);
p->file[P_SEL_AREA]->bind = 1; /* mount point */
snprintf(buf, sizeof(buf), "/%d/ctl", id);
p->file[P_CTL] = ixp_create(ixps, buf);
p->file[P_CTL]->after_write = handle_after_write_page;
alloc_area(p, "float");
alloc_area(p, def[WM_LAYOUT]->content);
cext_attach_item(pages, p);
snprintf(buf2, sizeof(buf2), "%d", npages);
snprintf(buf, sizeof(buf), "/%d", npages);
new->file[P_PREFIX] = ixp_create(ixps, buf);
snprintf(buf, sizeof(buf), "/%d/name", npages);
new->file[P_NAME] = wmii_create_ixpfile(ixps, buf, buf2);
snprintf(buf, sizeof(buf), "/%d/layout/", npages);
new->file[P_AREA_PREFIX] = ixp_create(ixps, buf);
snprintf(buf, sizeof(buf), "/%d/layout/sel", npages);
new->file[P_SEL_AREA] = ixp_create(ixps, buf);
new->file[P_SEL_AREA]->bind = 1; /* mount point */
snprintf(buf, sizeof(buf), "/%d/ctl", npages);
new->file[P_CTL] = ixp_create(ixps, buf);
new->file[P_CTL]->after_write = handle_after_write_page;
new->floating = alloc_area(new, "float");
new->sel = new->managed = alloc_area(new, def[WM_LAYOUT]->content);
for (p = pages; p && p->next; p = p->next);
if (!p)
pages = new;
else {
new->prev = p;
p->next = new;
}
selpage = new;
def[WM_SEL_PAGE]->content = p->file[P_PREFIX]->content;
invoke_wm_event(def[WM_EVENT_PAGE_UPDATE]);
return p;
}
static void iter_destroy_area(void *area, void *aux)
void destroy_page(Page *p)
{
destroy_area((Area *)area);
}
void destroy_page(Page * p)
{
cext_list_iterate(&p->areas, nil, iter_destroy_area);
destroy_area(p->floating);
destroy_area(p->managed);
def[WM_SEL_PAGE]->content = 0;
ixp_remove_file(ixps, p->file[P_PREFIX]);
cext_detach_item(pages, p);
if (p == selpage) {
if (p->prev)
selpage = p->prev;
else
selpage = nil;
}
if (p == pages) {
if (p->next)
p->next->prev = nil;
pages = p->next;
}
else {
p->prev->next = p->next;
if (p->next)
p->next->prev = p->prev;
}
free(p);
if ((p = get_sel_page()))
sel_page(p);
else
invoke_wm_event(def[WM_EVENT_PAGE_UPDATE]);
if (!selpage)
selpage = pages;
if (selpage)
focus_page(selpage);
}
void sel_page(Page * p)
void focus_page(Page *p)
{
Page *sel = get_sel_page();
if (!sel)
return;
if (p != sel) {
hide_page(sel);
cext_stack_top_item(pages, p);
show_page(p);
}
if (selpage != p)
hide_page(selpage);
selpage = p;
show_page(p);
def[WM_SEL_PAGE]->content = p->file[P_PREFIX]->content;
invoke_wm_event(def[WM_EVENT_PAGE_UPDATE]);
sel_area(get_sel_area());
focus_area(sel_area());
}
XRectangle *rectangles(unsigned int *num)
@ -109,57 +125,46 @@ XRectangle *rectangles(unsigned int *num)
return result;
}
static void iter_hide_page(void *item, void *aux)
void hide_page(Page *p)
{
hide_area((Area *)item);
hide_area(p->managed);
hide_area(p->floating);
}
void hide_page(Page * p)
void show_page(Page *p)
{
cext_list_iterate(&p->areas, nil, iter_hide_page);
show_area(p->managed, False);
show_area(p->floating, False);
}
static void iter_show_page(void *item, void *aux)
static void handle_after_write_page(IXPServer *s, File *file)
{
show_area((Area *)item);
}
void show_page(Page * p)
{
cext_list_iterate(&p->areas, nil, iter_show_page);
}
static void iter_after_write_page(void *item, void *aux)
{
Page *p = (Page *)item;
File *file = aux;
if (file == p->file[P_CTL]) {
run_action(file, p, page_acttbl);
return;
Page *p;
for (p = pages; p; p = p->next) {
if (file == p->file[P_CTL]) {
run_action(file, p, page_acttbl);
return;
}
}
}
static void handle_after_write_page(IXPServer *s, File *f)
{
cext_list_iterate(pages, f, iter_after_write_page);
}
Page *get_sel_page()
{
return cext_stack_get_top_item(pages);
}
static void select_area(void *obj, char *arg)
static void toggle_area(void *obj, char *arg)
{
Page *p = obj;
Area *a = cext_stack_get_top_item(&p->areas);
if (!strncmp(arg, "prev", 5))
a = cext_list_get_prev_item(&p->areas, a);
else if (!strncmp(arg, "next", 5))
a = cext_list_get_next_item(&p->areas, a);
else
a = cext_list_get_item(&p->areas, blitz_strtonum(arg, 0, cext_sizeof_container(&p->areas) - 1));
sel_area(a);
if (p->sel == p->managed)
p->sel = p->floating;
else
p->sel = p->managed;
sel_area(p->sel);
invoke_wm_event(def[WM_EVENT_PAGE_UPDATE]);
}
Page *get_page(unsigned int idx)
{
unsigned int i = 0;
Page *p = pages;
for (; p && i != idx; p = p->next);
return p;
}

View File

@ -113,36 +113,35 @@ scale_rect(XRectangle * from_dim, XRectangle * to_dim,
tgt->height = 1;
}
static void iter_draw_pager_frame(void *item, void *aux)
static void draw_pager_area(Area *a, Draw *d)
{
Draw *d = aux;
Frame *f = (Frame *)item;
if (f == get_sel_frame_of_area(f->area)) {
d->bg = blitz_loadcolor(dpy, screen_num, def[WM_SEL_BG_COLOR]->content);
d->fg = blitz_loadcolor(dpy, screen_num, def[WM_SEL_FG_COLOR]->content);
d->border = blitz_loadcolor(dpy, screen_num, def[WM_SEL_BORDER_COLOR]->content);
} else {
d->bg = blitz_loadcolor(dpy, screen_num, def[WM_NORM_BG_COLOR]->content);
d->fg = blitz_loadcolor(dpy, screen_num, def[WM_NORM_FG_COLOR]->content);
d->border = blitz_loadcolor(dpy, screen_num, def[WM_NORM_BORDER_COLOR]->content);
Frame *f;
Frame *sel = sel_frame();
for (f = bottom_frame(a->layout->frames(a)); f; f = f->prev) {
if (f == sel) {
d->bg = blitz_loadcolor(dpy, screen_num, def[WM_SEL_BG_COLOR]->content);
d->fg = blitz_loadcolor(dpy, screen_num, def[WM_SEL_FG_COLOR]->content);
d->border = blitz_loadcolor(dpy, screen_num, def[WM_SEL_BORDER_COLOR]->content);
} else {
d->bg = blitz_loadcolor(dpy, screen_num, def[WM_NORM_BG_COLOR]->content);
d->fg = blitz_loadcolor(dpy, screen_num, def[WM_NORM_FG_COLOR]->content);
d->border = blitz_loadcolor(dpy, screen_num, def[WM_NORM_BORDER_COLOR]->content);
}
d->data = f->sel->file[C_NAME]->content;
scale_rect(&rect, &initial_rect, &f->rect, &d->rect);
blitz_drawlabel(dpy, d);
XSync(dpy, False); /* do not clear upwards */
}
d->data = ((Client *)cext_stack_get_top_item(&f->clients))->file[C_NAME]->content;
scale_rect(&rect, &initial_rect, &f->rect, &d->rect);
blitz_drawlabel(dpy, d);
XSync(dpy, False); /* do not clear upwards */
}
static void draw_pager_area(void *item, void *aux)
{
Area *a = (Area *)item;
cext_stack_iterate_up(a->layout->get_frames(a), aux, iter_draw_pager_frame);
}
static void draw_pager_page(Page *p, Draw *d)
{
unsigned int idx = 0;
char name[4];
initial_rect = d->rect;
if (p == cext_stack_get_top_item(pages)) {
Page *page;
if (p == selpage) {
d->bg = blitz_loadcolor(dpy, screen_num, def[WM_SEL_BG_COLOR]->content);
d->fg = blitz_loadcolor(dpy, screen_num, def[WM_SEL_FG_COLOR]->content);
d->border = blitz_loadcolor(dpy, screen_num, def[WM_SEL_BORDER_COLOR]->content);
@ -151,28 +150,31 @@ static void draw_pager_page(Page *p, Draw *d)
d->fg = blitz_loadcolor(dpy, screen_num, def[WM_NORM_FG_COLOR]->content);
d->border = blitz_loadcolor(dpy, screen_num, def[WM_NORM_BORDER_COLOR]->content);
}
snprintf(name, sizeof(name), "%d", cext_list_get_item_index(pages, p));
for (page = pages; page && page != p; page = page->next) idx++;
snprintf(name, sizeof(name), "%d", idx);
d->data = name;
blitz_drawlabel(dpy, d);
XSync(dpy, False);
cext_stack_iterate_up(&p->areas, d, draw_pager_area);
if (p->managed)
draw_pager_area(p->managed, d);
draw_pager_area(p->floating, d);
}
static void draw_pager()
{
Draw d = { 0 };
unsigned int ic, ir, tw, th, rows, cols, size;
int i = 0;
unsigned int ic, ir, tw, th, rows, cols;
int dx;
Page *p;
blitz_getbasegeometry(pages, &size, &cols, &rows);
blitz_getbasegeometry(npages, &cols, &rows);
dx = (cols - 1) * GAP; /* GAPpx space */
tw = (rect.width - dx) / cols;
th = ((double) tw / rect.width) * rect.height;
d.drawable = transient;
d.gc = transient_gc;
d.font = font;
p = pages;
for (ir = 0; ir < rows; ir++) {
for (ic = 0; ic < cols; ic++) {
d.rect.x = ic * tw + (ic * GAP);
@ -182,29 +184,26 @@ static void draw_pager()
else
d.rect.y = ir * (rect.height - th) / (rows - 1);
d.rect.height = th;
if (!(p = cext_list_get_item(pages, i)))
if (!p->next)
return;
draw_pager_page(p, &d);
i++;
}
}
}
static Page *xy_to_pager_page(int x, int y)
{
unsigned int ic, ir, tw, th, rows, cols, size;
int i = 0;
unsigned int ic, ir, tw, th, rows, cols;
int dx;
XRectangle r;
Page *p;
if (!cext_sizeof_container(pages))
return nil;
blitz_getbasegeometry(pages, &size, &cols, &rows);
blitz_getbasegeometry(npages, &cols, &rows);
dx = (cols - 1) * GAP; /* GAPpx space */
tw = (rect.width - dx) / cols;
th = ((double) tw / rect.width) * rect.height;
p = pages;
for (ir = 0; ir < rows; ir++) {
for (ic = 0; ic < cols; ic++) {
r.x = ic * tw + (ic * GAP);
@ -214,11 +213,10 @@ static Page *xy_to_pager_page(int x, int y)
else
r.y = ir * (rect.height - th) / (rows - 1);
r.height = th;
if (!(p = cext_list_get_item(pages, i)))
if (!p->next)
return nil;
if (blitz_ispointinrect(x, y, &r))
return p;
i++;
}
}
return nil;
@ -241,7 +239,7 @@ static void pager(void *obj, char *arg)
XEvent ev;
int i;
if (!cext_sizeof_container(pages))
if (!pages)
return;
XClearWindow(dpy, transient);
@ -265,8 +263,8 @@ static void pager(void *obj, char *arg)
case KeyPress:
XUnmapWindow(dpy, transient);
if ((i = handle_kpress(&ev.xkey)) != -1)
if (i < cext_sizeof_container(pages))
sel_page(cext_list_get_item(pages, i));
if (i < npages)
focus_page(pageat(i));
XUngrabKeyboard(dpy, CurrentTime);
XUngrabPointer(dpy, CurrentTime /* ev.xbutton.time */ );
return;
@ -276,7 +274,7 @@ static void pager(void *obj, char *arg)
if (ev.xbutton.button == Button1) {
Page *p = xy_to_pager_page(ev.xbutton.x, ev.xbutton.y);
if (p)
sel_page(p);
focus_page(p);
}
XUngrabKeyboard(dpy, CurrentTime);
XUngrabPointer(dpy, CurrentTime /* ev.xbutton.time */ );
@ -288,12 +286,14 @@ static void pager(void *obj, char *arg)
static void draw_detached_clients()
{
unsigned int i, ic, ir, tw, th, rows, cols, size;
unsigned int ic, ir, tw, th, rows, cols;
int dx, dy;
Client *c = detached;
XRectangle cr;
if (!cext_sizeof_container(detached))
if (!c)
return;
blitz_getbasegeometry(detached, &size, &cols, &rows);
blitz_getbasegeometry(ndetached, &cols, &rows);
dx = (cols - 1) * GAP; /* GAPpx space */
dy = (rows - 1) * GAP; /* GAPpx space */
tw = (rect.width - dx) / cols;
@ -301,24 +301,21 @@ static void draw_detached_clients()
XClearWindow(dpy, transient);
XMapRaised(dpy, transient);
i = 0;
for (ir = 0; ir < rows; ir++) {
for (ic = 0; ic < cols; ic++) {
Client *c = cext_list_get_item(detached, i++);
XRectangle cr;
if (!c)
return;
cr.x = ic * tw + (ic * GAP);
cr.y = ir * th + (ir * GAP);
cr.width = tw;
cr.height = th;
XMoveResizeWindow(dpy, c->win, cr.x, cr.y, cr.width,
cr.height);
XMoveResizeWindow(dpy, c->win, cr.x, cr.y, cr.width, cr.height);
configure_client(c);
show_client(c);
XRaiseWindow(dpy, c->win);
grab_client(c, AnyModifier, AnyButton);
XSync(dpy, False);
c = c->next;
}
}
}
@ -334,13 +331,9 @@ static void reserve_area(void *obj, char *arg)
static void detached_clients(void *obj, char *arg)
{
XEvent ev;
int i, n;
size_t size = cext_sizeof_container(detached);
int n;
Client *c;
if (!size)
return;
XClearWindow(dpy, transient);
XMapRaised(dpy, transient);
draw_detached_clients();
@ -355,30 +348,25 @@ static void detached_clients(void *obj, char *arg)
switch (ev.type) {
case KeyPress:
XUnmapWindow(dpy, transient);
for (c = detached; c; c = c->next)
hide_client(c);
if ((n = handle_kpress(&ev.xkey)) != -1) {
for (i = 0; i < size; i++)
hide_client(cext_list_get_item(detached, i));
if (n - 1 < i) {
c = cext_list_get_item(detached, n);
cext_detach_item(detached, c);
if (n - 1 < ndetached) {
c = clientat(detached, n);
detach_detached(c);
attach_client(c);
}
} else {
for (i = 0; i < size; i++)
hide_client(cext_list_get_item(detached, i));
}
XUngrabKeyboard(dpy, CurrentTime);
return;
break;
case ButtonPress:
if (ev.xbutton.button == Button1) {
XUnmapWindow(dpy, transient);
for (i = 0; i < size; i++)
hide_client(cext_list_get_item(detached, i));
if ((c = win_to_client(ev.xbutton.window))) {
cext_detach_item(detached, c);
attach_client(c);
}
XUnmapWindow(dpy, transient);
for (c = detached; c; c = c->next)
hide_client(c);
if ((ev.xbutton.button == Button1) && (c = win_to_client(ev.xbutton.window))) {
detach_detached(c);
attach_client(c);
}
XUngrabKeyboard(dpy, CurrentTime);
return;
@ -389,70 +377,80 @@ static void detached_clients(void *obj, char *arg)
static void _close_client(void *obj, char *arg)
{
Frame *f = get_sel_frame();
if (f)
close_client(cext_stack_get_top_item(&f->clients));
Client *c = sel_client();
if (c)
close_client(c);
}
static void _attach_client(void *obj, char *arg)
{
if (cext_sizeof_container(detached)) {
Client *c = cext_stack_get_top_item(detached);
cext_detach_item(detached, c);
Client *c = detached;
if (c) {
detach_detached(c);
attach_client(c);
}
}
static void _detach_client(void *obj, char *arg)
{
Client *c = get_sel_client();
Client *c = sel_client();
if (c)
detach_client(c, False);
}
static void _select_page(void *obj, char *arg)
{
Page *p = get_sel_page();
Page *p = selpage;
if (!p || !arg)
return;
if (!strncmp(arg, "prev", 5))
p = cext_list_get_prev_item(pages, p);
p = p->prev;
else if (!strncmp(arg, "next", 5))
p = cext_list_get_next_item(pages, p);
p = p->next;
else
p = cext_list_get_item(pages, blitz_strtonum(arg, 0, cext_sizeof_container(pages) - 1));
sel_page(p);
p = pageat(blitz_strtonum(arg, 0, npages - 1));
if (p)
focus_page(p);
}
static void _destroy_page(void *obj, char *arg)
{
Page *p = get_sel_page();
Page *p = selpage;
if (p)
destroy_page(p);
p = get_sel_page();
if (p)
sel_page(p);
if (selpage)
focus_page(selpage);
}
static void new_page(void *obj, char *arg)
{
Page *p = get_sel_page();
Page *p = selpage;
if (p)
hide_page(p);
alloc_page();
}
static int comp_client_win(void *pattern, void *client)
{
Window w = *(Window *)pattern;
Client *c = client;
return c->win == w;
}
Client *win_to_client(Window w)
{
return cext_find_item(clients, &w, comp_client_win);
Page *p;
Client *c;
for (c = detached; c; c = c->next)
if (c->win == w)
return c;
for (p = pages; p; p = p->next) {
Frame *f;
for (f = p->managed->layout->frames(p->managed); f; f = f->next) {
for (c = f->clients; c; c = c->next)
if (c->win == w)
return c;
}
for (f = p->floating->layout->frames(p->floating); f; f = f->next) {
for (c = f->clients; c; c = c->next)
if (c->win == w)
return c;
}
}
return nil;
}
void scan_wins()
@ -533,16 +531,14 @@ int win_state(Window w)
return res;
}
static void iter_update_area(void *area, void *aux)
static void update_pages()
{
Area *a = area;
a->layout->arrange(a);
}
Page *p;
static void iter_update_page(void *page, void *aux)
{
Page *p = page;
cext_list_iterate(&p->areas, nil, iter_update_area);
for (p = pages; p; p = p->next) {
p->floating->layout->arrange(p->floating);
p->managed->layout->arrange(p->managed);
}
}
void handle_before_read(IXPServer *s, File *f)
@ -579,7 +575,7 @@ void handle_after_write(IXPServer * s, File * f)
if (geom && strrchr(geom, ',')) {
area_rect = rect;
blitz_strtorect(&rect, &area_rect, geom);
cext_list_iterate(pages, nil, iter_update_page);
update_pages();
}
}
check_event(0);
@ -708,14 +704,21 @@ static int startup_error_handler(Display * dpy, XErrorEvent * error)
return -1;
}
static void clean_client_up(void *item, void *aux)
{
detach_client(item, False);
}
static void cleanup()
{
cext_list_iterate(clients, nil, clean_client_up);
Page *p;
Client *c;
for (p = pages; p; p = p->next) {
Frame *f;
for (f = p->managed->layout->frames(p->managed); f; f = f->next) {
while ((c = f->clients))
detach_client_from_frame(c, False);
}
for (f = p->floating->layout->frames(p->floating); f; f = f->next) {
while ((c = f->clients))
detach_client_from_frame(c, False);
}
}
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
}
@ -785,12 +788,10 @@ int main(int argc, char *argv[])
}
def[WM_CTL]->after_write = handle_after_write;
detached = cext_emallocz(sizeof(Container));
pages = cext_emallocz(sizeof(Container));
areas = cext_emallocz(sizeof(Container));
frames = cext_emallocz(sizeof(Container));
clients = cext_emallocz(sizeof(Container));
layouts = cext_emallocz(sizeof(Container));
pages = selpage = nil;
ndetached = npages = 0;
detached = nil;
layouts = nil;
init_atoms();
init_cursors();

View File

@ -105,27 +105,32 @@ typedef struct Frame Frame;
typedef struct Client Client;
struct Page {
Container areas;
Area *managed;
Area *floating;
Area *sel;
File *file[P_LAST];
Page *next;
Page *prev;
};
struct Layout {
char *name;
void (*init) (Area *); /* called when layout is initialized */
void (*deinit) (Area *); /* called when layout is uninitialized */
void (*arrange) (Area *); /* called when area is resized */
Bool (*attach) (Area *, Client *); /* called on attach */
void (*detach) (Area *, Client *, Bool unmap); /* called on detach */
void (*resize) (Frame *, XRectangle *, XPoint *); /* called after resize */
void (*select) (Frame *, Bool raise); /* selection */
Container *(*get_frames) (Area *); /* called for drawing */
Action *(*get_actions) (Area *); /* local action table */
void (*init) (Area *, Client *); /* called when layout is initialized */
Client *(*deinit) (Area *); /* called when layout is uninitialized */
void (*arrange) (Area *); /* called when area is resized */
Bool (*attach) (Area *, Client *); /* called on attach */
void (*detach) (Area *, Client *, Bool unmap); /* called on detach */
void (*resize) (Frame *, XRectangle *, XPoint *); /* called after resize */
void (*focus) (Frame *, Bool raise); /* focussing a frame */
Frame *(*frames) (Area *); /* called for drawing */
Frame *(*sel) (Area *); /* returns selected frame */
Action *(*actions) (Area *); /* local action table */
Layout *next;
};
struct Area {
Page *page;
Layout *layout;
Container clients;
void *aux; /* free pointer */
File *file[A_LAST];
};
@ -133,16 +138,19 @@ struct Area {
struct Frame {
Area *area;
Window win;
Container clients;
Client *sel;
Client *clients;
size_t nclients;
GC gc;
XRectangle rect;
Cursor cursor;
void *aux; /* free pointer */
File *file[F_LAST];
Frame *next;
Frame *prev;
};
struct Client {
Area *area;
int proto;
unsigned int border;
unsigned int ignore_unmap;
@ -153,10 +161,19 @@ struct Client {
XSizeHints size;
Frame *frame;
File *file[C_LAST];
Client *next;
Client *prev;
};
/* global variables */
Page *pages;
Page *selpage;
size_t npages;
Client *detached;
size_t ndetached;
Layout *layouts;
Display *dpy;
IXPServer *ixps;
int screen_num;
@ -164,12 +181,6 @@ Window root;
Window transient;
XRectangle rect;
XRectangle area_rect;
Container *detached;
Container *pages;
Container *areas;
Container *frames;
Container *clients;
Container *layouts;
XFontStruct *font;
XColor xorcolor;
GC xorgc;
@ -202,11 +213,11 @@ unsigned int valid_mask, num_lock_mask;
/* area.c */
Area *alloc_area(Page *p, char *layout);
void destroy_area(Area * a);
void sel_area(Area * a);
void hide_area(Area * a);
void show_area(Area * a);
Area *get_sel_area();
void destroy_area(Area *a);
void focus_area(Area *a);
void hide_area(Area *a);
void show_area(Area *a, Bool raise);
Area *sel_area();
void attach_frame_to_area(Area *a, Frame *f);
void detach_frame_from_area(Frame *f);
@ -217,7 +228,7 @@ void destroy_client(Client * c);
void configure_client(Client * c);
void handle_client_property(Client * c, XPropertyEvent * e);
void close_client(Client * c);
void draw_client(void *item, void *aux);
void draw_client(Client *client);
void draw_clients(Frame * f);
void gravitate(Client * c, unsigned int tabh, unsigned int bw, int invert);
void grab_client(Client * c, unsigned long mod, unsigned int button);
@ -225,10 +236,13 @@ void ungrab_client(Client * c, unsigned long mod, unsigned int button);
void hide_client(Client * c);
void show_client(Client * c);
void reparent_client(Client * c, Window w, int x, int y);
void sel_client(Client *c);
void focus_client(Client *c);
void attach_client(Client *c);
void detach_client(Client *c, Bool unmap);
Client *get_sel_client();
Client *sel_client();
Client *clientat(Client *clients, size_t idx);
void detach_detached(Client *c);
void attach_detached(Client *c);
/* frame.c */
Frame *win_to_frame(Window w);
@ -237,12 +251,12 @@ void destroy_frame(Frame * f);
void resize_frame(Frame *f, XRectangle *r, XPoint *pt);
void draw_frame(Frame *f);
void handle_frame_buttonpress(XButtonEvent *e, Frame *f);
void attach_client_to_frame(Frame *f, Client *c);
void detach_client_from_frame(Client *c, Bool unmap);
void attach_client_to_frame(Frame *f, Client *client);
void detach_client_from_frame(Client *client, Bool unmap);
unsigned int tab_height(Frame * f);
unsigned int border_width(Frame * f);
Frame *get_sel_frame();
Frame *get_sel_frame_of_area(Area *a);
Frame *sel_frame();
Frame *bottom_frame(Frame *frames);
/* event.c */
void init_event_hander();
@ -258,17 +272,17 @@ void drop_move(Frame * f, XRectangle * new, XPoint * pt);
void center_pointer(Frame * f);
/* page.c */
Page *get_sel_page();
Page *pageat(unsigned int idx);
Page *alloc_page();
void free_page(Page * p);
void destroy_page(Page * p);
void sel_page(Page *p);
void focus_page(Page *p);
XRectangle *rectangles(unsigned int *num);
void hide_page(Page * p);
void show_page(Page * p);
/* layout.c */
Layout *get_layout(char *name);
Layout *match_layout(char *name);
/* layoutdef.c */
void init_layouts();

View File

@ -11,7 +11,7 @@ LIBDIR = ${PREFIX}/lib
X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib
VERSION = 20051215
VERSION = 3-current
# includes and libs
INCLUDES = -I. -I${INCDIR} -I/usr/include -I${X11INC}

View File

@ -3,7 +3,7 @@
include ../config.mk
SRC = container.c emallocz.c estrdup.c strlcat.c strlcpy.c strtonum.c tokenize.c
SRC = emallocz.c estrdup.c strlcat.c strlcpy.c strtonum.c tokenize.c
OBJ = ${SRC:.c=.o}

View File

@ -15,39 +15,6 @@
#define TRUE 1
#endif
/* container.c */
typedef struct Container Container;
typedef struct CItem CItem;
struct CItem {
void *item;
CItem *next;
CItem *up;
CItem *down;
};
struct Container {
CItem *list;
CItem *stack;
};
void cext_attach_item(Container *c, void *item);
void cext_detach_item(Container *c, void *item);
void *cext_find_item(Container *c, void *pattern, int (*comp)(void *pattern, void *item));
void cext_swap_items(Container *c, void *item1, void *item2);
size_t cext_sizeof_container(Container *c);
void cext_stack_top_item(Container *c, void *item);
void *cext_stack_get_top_item(Container *c);
void *cext_stack_get_down_item(Container *c, void *item);
void *cext_stack_get_up_item(Container *c, void *item);
void cext_stack_iterate_down(Container *c, void *aux, void (*iter)(void *, void *aux));
void cext_stack_iterate_up(Container *c, void *aux, void (*iter)(void *, void *aux));
void cext_list_iterate(Container *c, void *aux, void (*iter)(void *, void *aux));
void *cext_list_get_item(Container *c, size_t index);
int cext_list_get_item_index(Container *c, void *item);
void *cext_list_get_next_item(Container *c, void *item);
void *cext_list_get_prev_item(Container *c, void *item);
/* emallocz.c */
void *cext_emallocz(size_t size);

View File

@ -1,227 +0,0 @@
/*
* (C)opyright MMIV-MMV Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include <assert.h>
#include <stdlib.h>
#include "cext.h"
static int comp_ptr(void *p1, void *p2)
{
return p1 == p2;
}
static void detach_from_stack(Container *c, CItem *i)
{
/* remove from stack */
if (i == c->stack) {
c->stack = i->down;
if (c->stack)
c->stack->up = 0;
}
else {
if (i->up)
i->up->down = i->down;
if (i->down)
i->down->up = i->up;
}
i->up = 0;
i->down = 0;
}
static void attach_to_stack(Container *c, CItem *i)
{
i->up = 0;
i->down = 0;
if (!c->stack)
c->stack = i;
else {
i->down = c->stack;
c->stack->up = i;
c->stack = i;
}
}
void cext_attach_item(Container *c, void *item)
{
CItem *i, *new = cext_emallocz(sizeof(CItem));
new->item = item;
if (!c->list)
c->list = new;
else {
for (i = c->list; i->next; i = i->next);
i->next = new;
}
attach_to_stack(c, new);
}
void cext_detach_item(Container *c, void *item)
{
CItem *i = c->list;
if (!i)
return;
/* remove from list */
if (i->item == item)
c->list = i->next;
else {
CItem *tmp;
for (; i->next && (i->next->item != item); i = i->next);
if (!i->next)
return;
tmp = i;
i = i->next;
tmp->next = tmp->next->next;
}
detach_from_stack(c, i);
free(i);
}
static CItem *cext_find_citem(Container *c, void *pattern, int (*comp)(void *pattern, void *item))
{
CItem *i;
for (i = c->list; i && !comp(pattern, i->item); i = i->next);
return i;
}
void *cext_find_item(Container *c, void *pattern, int (*comp)(void *pattern, void *item))
{
CItem *i = cext_find_citem(c, pattern, comp);
return i ? i->item : nil;
}
size_t cext_sizeof_container(Container *c)
{
size_t idx = 0;
CItem *i;
for (i = c->list; i; i = i->next)
idx++;
return idx;
}
void cext_swap_items(Container *c, void *item1, void *item2)
{
CItem *i1 = cext_find_citem(c, item1, comp_ptr);
CItem *i2 = cext_find_citem(c, item2, comp_ptr);
i1->item = item2;
i2->item = item1;
}
void cext_stack_top_item(Container *c, void *item)
{
CItem *i = cext_find_citem(c, item, comp_ptr);
if (!i)
return;
detach_from_stack(c, i);
attach_to_stack(c, i);
}
void *cext_stack_get_top_item(Container *c)
{
return c->stack ? c->stack->item : nil;
}
void *cext_stack_get_down_item(Container *c, void *item)
{
CItem *i = cext_find_citem(c, item, comp_ptr);
if (!i)
return nil;
return i->down ? i->down->item : c->stack->item;
}
void *cext_stack_get_up_item(Container *c, void *item)
{
CItem *i = cext_find_citem(c, item, comp_ptr);
CItem *bottom;
if (!i)
return nil;
for (bottom = c->stack; bottom && bottom->down; bottom = bottom->down);
return i->up ? i->up->item : bottom->item;
}
void cext_stack_iterate_down(Container *c, void *aux, void (*iter)(void *, void *aux))
{
CItem *i;
for (i = c->stack; i; i = i->down)
{
assert(c);
assert(i->item);
iter(i->item, aux);
}
}
void cext_stack_iterate_up(Container *c, void *aux, void (*iter)(void *, void *aux))
{
CItem *i;
for (i = c->stack; i && i->down; i = i->down);
for (; i; i = i->up)
{
assert(c);
assert(i->item);
iter(i->item, aux);
}
}
void cext_list_iterate(Container *c, void *aux, void (*iter)(void *, void *aux))
{
CItem *i;
for (i = c->list; i; i = i->next)
{
assert(c);
assert(i->item);
iter(i->item, aux);
}
}
void *cext_list_get_item(Container *c, size_t index)
{
size_t idx = 0;
CItem *i;
for (i = c->list; i && index != idx; i = i->next)
idx++;
return i ? i->item : nil;
}
int cext_list_get_item_index(Container *c, void *item)
{
int idx = 0;
CItem *i;
for (i = c->list; i && i->item != item; i = i->next)
idx++;
return i ? idx : -1;
}
void *cext_list_get_next_item(Container *c, void *item)
{
size_t size = cext_sizeof_container(c);
int idx = cext_list_get_item_index(c, item);
if (idx == -1)
return nil;
if (idx + 1 < size)
return cext_list_get_item(c, idx + 1);
else
return cext_list_get_item(c, 0);
}
void *cext_list_get_prev_item(Container *c, void *item)
{
size_t size = cext_sizeof_container(c);
int idx = cext_list_get_item_index(c, item);
if (idx == -1)
return nil;
if (idx - 1 < 0)
return cext_list_get_item(c, size - 1);
else
return cext_list_get_item(c, idx - 1);
}

View File

@ -45,7 +45,7 @@ void blitz_drawlabelnoborder(Display * dpy, Draw * r);
int blitz_strtorect(XRectangle * root, XRectangle * r, char *val);
Bool blitz_ispointinrect(int x, int y, XRectangle * r);
int blitz_distance(XRectangle * origin, XRectangle * target);
void blitz_getbasegeometry(Container *c, unsigned int *size, unsigned int *cols, unsigned int *rows);
void blitz_getbasegeometry(unsigned int size, unsigned int *cols, unsigned int *rows);
/* mouse.c */
char *blitz_buttontostr(unsigned int button);

View File

@ -198,15 +198,14 @@ int blitz_distance(XRectangle * origin, XRectangle * target)
return (int) sqrt((double) (((ox - tx) * (ox - tx)) + ((oy - ty) * (oy - ty))));
}
void blitz_getbasegeometry(Container *c, unsigned int *size, unsigned int *cols, unsigned int *rows)
void blitz_getbasegeometry(unsigned int size, unsigned int *cols, unsigned int *rows)
{
float sq, dummy;
*size = cext_sizeof_container(c);
sq = sqrt(*size);
sq = sqrt(size);
if (modff(sq, &dummy) < 0.5)
*rows = floor(sq);
else
*rows = ceil(sq);
*cols = ((*rows) * (*rows)) < (*size) ? *rows + 1 : *rows;
*cols = ((*rows) * (*rows)) < (size) ? *rows + 1 : *rows;
}