From 8ece4071aefdaaa810227669fbbbfd38b5a44b03 Mon Sep 17 00:00:00 2001 From: garbeam Date: Fri, 16 Dec 2005 03:59:27 +0200 Subject: [PATCH] removing container, not finished yet, fixed a bunch of other nasty bugs reported so far --- cmd/wm/area.c | 107 ++++------ cmd/wm/client.c | 90 ++++++--- cmd/wm/event.c | 7 +- cmd/wm/frame.c | 250 +++++++++++++----------- cmd/wm/layout.c | 16 +- cmd/wm/layout_column.c | 434 +++++++++++++++++++++++++---------------- cmd/wm/page.c | 169 ++++++++-------- cmd/wm/wm.c | 233 +++++++++++----------- cmd/wm/wm.h | 82 ++++---- config.mk | 2 +- libcext/Makefile | 2 +- libcext/cext.h | 33 ---- libcext/container.c | 227 --------------------- liblitz/blitz.h | 2 +- liblitz/geometry.c | 7 +- 15 files changed, 766 insertions(+), 895 deletions(-) delete mode 100644 libcext/container.c diff --git a/cmd/wm/area.c b/cmd/wm/area.c index b8e52588..4271b364 100644 --- a/cmd/wm/area.c +++ b/cmd/wm/area.c @@ -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); -} - - - diff --git a/cmd/wm/client.c b/cmd/wm/client.c index ca5014a9..29d61bff 100644 --- a/cmd/wm/client.c +++ b/cmd/wm/client.c @@ -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; } diff --git a/cmd/wm/event.c b/cmd/wm/event.c index 4f4b9d82..5451c8ec 100644 --- a/cmd/wm/event.c +++ b/cmd/wm/event.c @@ -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); } } diff --git a/cmd/wm/frame.c b/cmd/wm/frame.c index df424b35..ccdecd13 100644 --- a/cmd/wm/frame.c +++ b/cmd/wm/frame.c @@ -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; } diff --git a/cmd/wm/layout.c b/cmd/wm/layout.c index e236d3b8..1ec5bad7 100644 --- a/cmd/wm/layout.c +++ b/cmd/wm/layout.c @@ -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; } diff --git a/cmd/wm/layout_column.c b/cmd/wm/layout_column.c index 3e523b33..d5158548 100644 --- a/cmd/wm/layout_column.c +++ b/cmd/wm/layout_column.c @@ -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); } + diff --git a/cmd/wm/page.c b/cmd/wm/page.c index 8381f02e..61204955 100644 --- a/cmd/wm/page.c +++ b/cmd/wm/page.c @@ -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; +} diff --git a/cmd/wm/wm.c b/cmd/wm/wm.c index f6f1d5b8..dc247690 100644 --- a/cmd/wm/wm.c +++ b/cmd/wm/wm.c @@ -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(); diff --git a/cmd/wm/wm.h b/cmd/wm/wm.h index 89cfe657..3df5325b 100644 --- a/cmd/wm/wm.h +++ b/cmd/wm/wm.h @@ -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(); diff --git a/config.mk b/config.mk index 4556dc08..19b5b668 100644 --- a/config.mk +++ b/config.mk @@ -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} diff --git a/libcext/Makefile b/libcext/Makefile index d3f1f8d7..911d3ec9 100644 --- a/libcext/Makefile +++ b/libcext/Makefile @@ -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} diff --git a/libcext/cext.h b/libcext/cext.h index 40f1a841..84dd8732 100644 --- a/libcext/cext.h +++ b/libcext/cext.h @@ -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); diff --git a/libcext/container.c b/libcext/container.c deleted file mode 100644 index 9c6d08f5..00000000 --- a/libcext/container.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * (C)opyright MMIV-MMV Anselm R. Garbe - * See LICENSE file for license details. - */ - -#include -#include - -#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); -} diff --git a/liblitz/blitz.h b/liblitz/blitz.h index 2dd83911..e2f0e8c2 100644 --- a/liblitz/blitz.h +++ b/liblitz/blitz.h @@ -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); diff --git a/liblitz/geometry.c b/liblitz/geometry.c index 1d95274d..72dadffb 100644 --- a/liblitz/geometry.c +++ b/liblitz/geometry.c @@ -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; }