mirror of
https://github.com/0intro/wmii
synced 2024-12-26 05:16:59 +03:00
removing container, not finished yet, fixed a bunch of other nasty bugs reported so far
This commit is contained in:
parent
eb09a51b8b
commit
8ece4071ae
107
cmd/wm/area.c
107
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
250
cmd/wm/frame.c
250
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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
169
cmd/wm/page.c
169
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;
|
||||
}
|
||||
|
233
cmd/wm/wm.c
233
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();
|
||||
|
82
cmd/wm/wm.h
82
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();
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user