wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

commit e23ca5ca5924f543150d17c1c45cf7fa5dc26195
parent ea20f48ed0426c9a0ce1de2aadf3f426dd9f12e2
Author: Anselm R. Garbe <garbeam@wmii.de>
Date:   Thu,  2 Mar 2006 15:28:55 +0100

proceeded with sendtopage fixes


Diffstat:
cmd/wm/Makefile | 2+-
cmd/wm/area.c | 305++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
cmd/wm/bar.c | 2+-
cmd/wm/client.c | 8++++----
cmd/wm/column.c | 288-------------------------------------------------------------------------------
cmd/wm/fs.c | 8++++----
cmd/wm/wm.h | 18+++++++-----------
7 files changed, 311 insertions(+), 320 deletions(-)

diff --git a/cmd/wm/Makefile b/cmd/wm/Makefile @@ -9,7 +9,7 @@ LDFLAGS += -L../../liblitz -llitz -L../../libixp -lixp -L../../libcext -lcext # Solaris # LDFLAGS += -lsocket -SRC = area.c bar.c fs.c wm.c kb.c client.c event.c mouse.c page.c column.c +SRC = area.c bar.c fs.c wm.c kb.c client.c event.c mouse.c page.c OBJ = ${SRC:.c=.o} all: wmiiwm diff --git a/cmd/wm/area.c b/cmd/wm/area.c @@ -97,13 +97,7 @@ select_area(Area *a, char *arg) void sendto_area(Area *to, Client *c) { - Area *a = c->area; - - cext_array_detach((void **)a->client, c, &a->clientsz); - a->nclient--; - if(a->sel >= a->nclient) - a->sel = 0; - + detach_client_area(c); attach_client2area(to, c); focus_client(c); } @@ -134,8 +128,8 @@ attach_client2area(Area *a, Client *c) (void **)a->client, c, sizeof(Client *), &a->clientsz); a->nclient++; c->area = a; - if(p->sel > 0) /* column mode */ - arrange_column(a); + if(p->sel > 0) /* area mode */ + arrange_area(a); else /* normal mode */ resize_client(c, &c->frame.rect, nil, False); } @@ -150,7 +144,7 @@ detach_client_area(Client *c) a->nclient--; if(a->sel >= a->nclient) a->sel = 0; - if(i) { /* column */ + if(i) { /* area */ if(a->capacity && (a->nclient < a->capacity)) { for(++i; i < p->narea; i++) { Area *tmp = p->area[i]; @@ -171,6 +165,295 @@ detach_client_area(Client *c) } } else - arrange_column(a); + arrange_area(a); + } +} + +void +match_capacity(Area *a) +{ + while(a->nclient > a->capacity) { + Client *c = a->client[a->nclient - 1]; + detach_client_area(c); + attach_client(c); + } +} + +char * +colmode2str(ColumnMode mode) +{ + switch(mode) { + case COL_EQUAL: return "equal"; break; + case COL_STACK: return "stack"; break; + case COL_MAX: return "max"; break; + default: break; + } + return nil; +} + +ColumnMode +str2colmode(char *arg) +{ + if(!strncmp("equal", arg, 6)) + return COL_EQUAL; + if(!strncmp("stack", arg, 6)) + return COL_STACK; + if(!strncmp("max", arg, 4)) + return COL_MAX; + return -1; +} + +static void +relax_area(Area *a) +{ + unsigned int i, yoff, h, w, hdiff, wdiff; + + if(!a->nclient) + return; + + /* some relaxing from potential increment gaps */ + h = w = 0; + for(i = 0; i < a->nclient; i++) { + Client *c = a->client[i]; + if(a->mode == COL_MAX) { + if(h < c->frame.rect.height) + h = c->frame.rect.height; + } + else + h += c->frame.rect.height; + if(w < c->frame.rect.width) + w = c->frame.rect.width; + } + wdiff = (a->rect.width - w) / 2; + + /* try to add rest space to all clients if not COL_STACK mode */ + if(a->mode != COL_STACK) { + for(i = 0; (h < a->rect.height) && (i < a->nclient); i++) { + Client *c = a->client[i]; + unsigned int tmp = c->frame.rect.height; + c->frame.rect.height += (a->rect.height - h); + resize_client(c, &c->frame.rect, 0, True); + h += (c->frame.rect.height - tmp); + } + } + + hdiff = (a->rect.height - h) / a->nclient; + yoff = a->rect.y + hdiff / 2; + for(i = 0; i < a->nclient; i++) { + Client *c = a->client[i]; + c->frame.rect.x = a->rect.x + wdiff; + c->frame.rect.y = yoff; + if(a->mode != COL_MAX) + yoff = c->frame.rect.y + c->frame.rect.height + hdiff; + resize_client(c, &c->frame.rect, 0, False); + } +} + +void +arrange_area(Area *a) +{ + unsigned int i, yoff, h; + + if(!a->nclient) + return; + + switch(a->mode) { + case COL_EQUAL: + h = a->rect.height; + h /= a->nclient; + for(i = 0; i < a->nclient; i++) { + Client *c = a->client[i]; + c->frame.rect = a->rect; + c->frame.rect.y += i * h; + if(i + 1 < a->nclient) + c->frame.rect.height = h; + else + c->frame.rect.height = + a->rect.height - c->frame.rect.y + a->rect.y; + resize_client(c, &c->frame.rect, 0, True); + } + break; + case COL_STACK: + yoff = a->rect.y; + h = a->rect.height - (a->nclient - 1) * bar_height(); + for(i = 0; i < a->nclient; i++) { + Client *c = a->client[i]; + c->frame.rect = a->rect; + c->frame.rect.y = yoff; + if(i == a->sel) + c->frame.rect.height = h; + else + c->frame.rect.height = bar_height(); + yoff += c->frame.rect.height; + resize_client(c, &c->frame.rect, 0, True); + } + break; + case COL_MAX: + for(i = 0; i < a->nclient; i++) { + Client *c = a->client[i]; + c->frame.rect = a->rect; + resize_client(c, &c->frame.rect, 0, True); + } + break; + default: + break; + } + + relax_area(a); +} + +void +arrange_page(Page *p, Bool update_areas) +{ + unsigned int i; + unsigned int width; + + if(p->narea == 1) + return; + + width = rect.width / (p->narea - 1); + for(i = 1; i < p->narea; i++) { + Area *a = p->area[i]; + if(update_areas) { + update_area_geometry(a); + a->rect.x = (i - 1) * width; + a->rect.width = width; + } + arrange_area(a); } } + +static void +match_horiz(Area *a, XRectangle *r) +{ + unsigned int i; + + for(i = 0; i < a->nclient; i++) { + Client *c = a->client[i]; + c->frame.rect.x = r->x; + c->frame.rect.width = r->width; + resize_client(c, &c->frame.rect, nil, False); + } +} + +static void +drop_resize(Client *c, XRectangle *new) +{ + Area *west = nil, *east = nil, *a = c->area; + Page *p = a->page; + Client *north = nil, *south = nil; + unsigned int i; + + for(i = 1; (i < p->narea) && (p->area[i] != a); i++); + /* first managed area is indexed 1, thus (i > 1) ? ... */ + west = (i > 1) ? p->area[i - 1] : nil; + east = i + 1 < p->narea ? p->area[i + 1] : nil; + + for(i = 1; (i < a->nclient) && (a->client[i] != c); i++); + north = i ? a->client[i - 1] : nil; + south = i + 1 < a->nclient ? a->client[i + 1] : nil; + + /* horizontal resize */ + if(west && (new->x != c->frame.rect.x)) { + west->rect.width = new->x - west->rect.x; + a->rect.width += c->frame.rect.x - new->x; + a->rect.x = new->x; + match_horiz(west, &west->rect); + match_horiz(a, &a->rect); + relax_area(west); + } + if(east && (new->x + new->width != c->frame.rect.x + c->frame.rect.width)) { + east->rect.width -= new->x + new->width - east->rect.x; + east->rect.x = new->x + new->width; + a->rect.x = new->x; + a->rect.width = new->width; + match_horiz(a, &a->rect); + match_horiz(east, &east->rect); + relax_area(east); + } + + /* vertical resize */ + if(north && (new->y != c->frame.rect.y)) { + north->frame.rect.height = new->y - north->frame.rect.y; + c->frame.rect.height += c->frame.rect.y - new->y; + c->frame.rect.y = new->y; + resize_client(north, &north->frame.rect, nil, False); + resize_client(c, &c->frame.rect, nil, False); + } + if(south && (new->y + new->height != c->frame.rect.y + c->frame.rect.height)) { + south->frame.rect.height -= new->y + new->height - south->frame.rect.y; + south->frame.rect.y = new->y + new->height; + c->frame.rect.y = new->y; + c->frame.rect.height = new->height; + resize_client(c, &c->frame.rect, nil, False); + resize_client(south, &south->frame.rect, nil, False); + } + relax_area(a); +} + +static void +drop_moving(Client *c, XRectangle *new, XPoint * pt) +{ + Area *tgt = nil, *src = c->area; + Page *p = src->page; + unsigned int i; + + if(!pt || src->nclient < 2) + return; + + for(i = 1; (i < p->narea) && + !blitz_ispointinrect(pt->x, pt->y, &p->area[i]->rect); i++); + if((tgt = ((i < p->narea) ? p->area[i] : nil))) { + if(tgt != src) { + sendto_area(tgt, c); + arrange_area(tgt); + } + else { + for(i = 0; (i < src->nclient) && + !blitz_ispointinrect(pt->x, pt->y, &src->client[i]->frame.rect); i++); + if((i < src->nclient) && (c != src->client[i])) { + unsigned int j = client2index(c); + Client *tmp = src->client[j]; + src->client[j] = src->client[i]; + src->client[i] = tmp; + arrange_area(src); + focus_client(c); + } + } + } +} + +void +resize_area(Client *c, XRectangle *r, XPoint *pt) +{ + if((c->frame.rect.width == r->width) + && (c->frame.rect.height == r->height)) + drop_moving(c, r, pt); + else + drop_resize(c, r); +} + +Area * +new_area(Area *old) +{ + Page *p = old->page; + Client *c = sel_client_of_page(p); + Area *a; + + if(!area2index(old) || (old->nclient < 2)) + return nil; + + a = alloc_area(p); + cext_array_detach((void **)old->client, c, &old->clientsz); + old->nclient--; + if(old->sel == old->nclient) + old->sel = 0; + a->client = (Client **)cext_array_attach((void **)a->client, c, + sizeof(Client *), &a->clientsz); + a->nclient++; + + c->area = a; + arrange_page(p, True); + focus_client(c); + return a; +} diff --git a/cmd/wm/bar.c b/cmd/wm/bar.c @@ -49,7 +49,7 @@ update_bar_geometry() for(i = 0; i < npage; i++) for(j = 1; j < page[i]->narea; j++) { update_area_geometry(page[i]->area[j]); - arrange_column(page[i]->area[j]); + arrange_area(page[i]->area[j]); } } diff --git a/cmd/wm/client.c b/cmd/wm/client.c @@ -115,7 +115,7 @@ focus_client(Client *c) client_name_event(c); client_focus_event(c); if(i > 0 && c->area->mode == COL_STACK) - arrange_column(c->area); + arrange_area(c->area); } void @@ -473,7 +473,7 @@ resize_client(Client *c, XRectangle *r, XPoint *pt, Bool ignore_xcall) if(area2index(c->area) > 0) - resize_column(c, r, pt); + resize_area(c, r, pt); else c->frame.rect = *r; @@ -599,8 +599,8 @@ sendtoarea_client(Client *c, char *arg) { arrange_page(p, True); } else { - arrange_column(a); - arrange_column(to); + arrange_area(a); + arrange_area(to); } } diff --git a/cmd/wm/column.c b/cmd/wm/column.c @@ -1,288 +0,0 @@ -/* - * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> - * See LICENSE file for license details. - */ - -#include <stdlib.h> -#include <string.h> - -#include "wm.h" - -char * -colmode2str(ColumnMode mode) -{ - switch(mode) { - case COL_EQUAL: return "equal"; break; - case COL_STACK: return "stack"; break; - case COL_MAX: return "max"; break; - default: break; - } - return nil; -} - -ColumnMode -str2colmode(char *arg) -{ - if(!strncmp("equal", arg, 6)) - return COL_EQUAL; - if(!strncmp("stack", arg, 6)) - return COL_STACK; - if(!strncmp("max", arg, 4)) - return COL_MAX; - return -1; -} - -static void -relax_column(Area *col) -{ - unsigned int i, yoff, h, w, hdiff, wdiff; - - if(!col->nclient) - return; - - /* some relaxing from potential increment gaps */ - h = w = 0; - for(i = 0; i < col->nclient; i++) { - Client *c = col->client[i]; - if(col->mode == COL_MAX) { - if(h < c->frame.rect.height) - h = c->frame.rect.height; - } - else - h += c->frame.rect.height; - if(w < c->frame.rect.width) - w = c->frame.rect.width; - } - wdiff = (col->rect.width - w) / 2; - - /* try to add rest space to all clients if not COL_STACK mode */ - if(col->mode != COL_STACK) { - for(i = 0; (h < col->rect.height) && (i < col->nclient); i++) { - Client *c = col->client[i]; - unsigned int tmp = c->frame.rect.height; - c->frame.rect.height += (col->rect.height - h); - resize_client(c, &c->frame.rect, 0, True); - h += (c->frame.rect.height - tmp); - } - } - - hdiff = (col->rect.height - h) / col->nclient; - yoff = col->rect.y + hdiff / 2; - for(i = 0; i < col->nclient; i++) { - Client *c = col->client[i]; - c->frame.rect.x = col->rect.x + wdiff; - c->frame.rect.y = yoff; - if(col->mode != COL_MAX) - yoff = c->frame.rect.y + c->frame.rect.height + hdiff; - resize_client(c, &c->frame.rect, 0, False); - } -} - -void -arrange_column(Area *col) -{ - unsigned int i, yoff, h; - - if(!col->nclient) - return; - - switch(col->mode) { - case COL_EQUAL: - h = col->rect.height; - h /= col->nclient; - for(i = 0; i < col->nclient; i++) { - Client *c = col->client[i]; - c->frame.rect = col->rect; - c->frame.rect.y += i * h; - if(i + 1 < col->nclient) - c->frame.rect.height = h; - else - c->frame.rect.height = - col->rect.height - c->frame.rect.y + col->rect.y; - resize_client(c, &c->frame.rect, 0, True); - } - break; - case COL_STACK: - yoff = col->rect.y; - h = col->rect.height - (col->nclient - 1) * bar_height(); - for(i = 0; i < col->nclient; i++) { - Client *c = col->client[i]; - c->frame.rect = col->rect; - c->frame.rect.y = yoff; - if(i == col->sel) - c->frame.rect.height = h; - else - c->frame.rect.height = bar_height(); - yoff += c->frame.rect.height; - resize_client(c, &c->frame.rect, 0, True); - } - break; - case COL_MAX: - for(i = 0; i < col->nclient; i++) { - Client *c = col->client[i]; - c->frame.rect = col->rect; - resize_client(c, &c->frame.rect, 0, True); - } - break; - default: - break; - } - - relax_column(col); -} - -void -arrange_page(Page *p, Bool update_colums) -{ - unsigned int i; - unsigned int width; - - if(p->narea == 1) - return; - - width = rect.width / (p->narea - 1); - for(i = 1; i < p->narea; i++) { - Area *a = p->area[i]; - if(update_colums) { - update_area_geometry(a); - a->rect.x = (i - 1) * width; - a->rect.width = width; - } - arrange_column(a); - } -} - -static void -match_horiz(Area *col, XRectangle *r) -{ - unsigned int i; - - for(i = 0; i < col->nclient; i++) { - Client *c = col->client[i]; - c->frame.rect.x = r->x; - c->frame.rect.width = r->width; - resize_client(c, &c->frame.rect, nil, False); - } -} - -static void -drop_resize(Client *c, XRectangle *new) -{ - Area *west = nil, *east = nil, *col = c->area; - Page *p = col->page; - Client *north = nil, *south = nil; - unsigned int i; - - for(i = 1; (i < p->narea) && (p->area[i] != col); i++); - /* first managed area is indexed 1, thus (i > 1) ? ... */ - west = (i > 1) ? p->area[i - 1] : nil; - east = i + 1 < p->narea ? p->area[i + 1] : nil; - - for(i = 1; (i < col->nclient) && (col->client[i] != c); i++); - north = i ? col->client[i - 1] : nil; - south = i + 1 < col->nclient ? col->client[i + 1] : nil; - - /* horizontal resize */ - if(west && (new->x != c->frame.rect.x)) { - west->rect.width = new->x - west->rect.x; - col->rect.width += c->frame.rect.x - new->x; - col->rect.x = new->x; - match_horiz(west, &west->rect); - match_horiz(col, &col->rect); - relax_column(west); - } - if(east && (new->x + new->width != c->frame.rect.x + c->frame.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; - match_horiz(col, &col->rect); - match_horiz(east, &east->rect); - relax_column(east); - } - - /* vertical resize */ - if(north && (new->y != c->frame.rect.y)) { - north->frame.rect.height = new->y - north->frame.rect.y; - c->frame.rect.height += c->frame.rect.y - new->y; - c->frame.rect.y = new->y; - resize_client(north, &north->frame.rect, nil, False); - resize_client(c, &c->frame.rect, nil, False); - } - if(south && (new->y + new->height != c->frame.rect.y + c->frame.rect.height)) { - south->frame.rect.height -= new->y + new->height - south->frame.rect.y; - south->frame.rect.y = new->y + new->height; - c->frame.rect.y = new->y; - c->frame.rect.height = new->height; - resize_client(c, &c->frame.rect, nil, False); - resize_client(south, &south->frame.rect, nil, False); - } - relax_column(col); -} - -static void -drop_moving(Client *c, XRectangle *new, XPoint * pt) -{ - Area *tgt = nil, *src = c->area; - Page *p = src->page; - unsigned int i; - - if(!pt || src->nclient < 2) - return; - - for(i = 1; (i < p->narea) && - !blitz_ispointinrect(pt->x, pt->y, &p->area[i]->rect); i++); - if((tgt = ((i < p->narea) ? p->area[i] : nil))) { - if(tgt != src) { - sendto_area(tgt, c); - arrange_column(tgt); - } - else { - for(i = 0; (i < src->nclient) && - !blitz_ispointinrect(pt->x, pt->y, &src->client[i]->frame.rect); i++); - if((i < src->nclient) && (c != src->client[i])) { - unsigned int j = client2index(c); - Client *tmp = src->client[j]; - src->client[j] = src->client[i]; - src->client[i] = tmp; - arrange_column(src); - focus_client(c); - } - } - } -} - -void -resize_column(Client *c, XRectangle *r, XPoint *pt) -{ - if((c->frame.rect.width == r->width) - && (c->frame.rect.height == r->height)) - drop_moving(c, r, pt); - else - drop_resize(c, r); -} - -Area * -new_column(Area *old) -{ - Page *p = old->page; - Client *c = sel_client_of_page(p); - Area *col; - - if(!area2index(old) || (old->nclient < 2)) - return nil; - - col = alloc_area(p); - cext_array_detach((void **)old->client, c, &old->clientsz); - old->nclient--; - if(old->sel == old->nclient) - old->sel = 0; - col->client = (Client **)cext_array_attach((void **)col->client, c, - sizeof(Client *), &col->clientsz); - col->nclient++; - - c->area = col; - arrange_page(p, True); - focus_client(c); - return col; -} diff --git a/cmd/wm/fs.c b/cmd/wm/fs.c @@ -340,7 +340,7 @@ mkqid(Qid *dir, char *wname, Qid *new, Bool iswalk) new->type = IXP_QTDIR; if(!strncmp(wname, "new", 4)) { if(iswalk) { - Area *a = new_column(p->area[p->sel]); + Area *a = new_area(p->area[p->sel]); if(!a) return -1; new->path = mkqpath(Darea, p->id, a->id, 0); @@ -1191,7 +1191,7 @@ xwrite(IXPConn *c, Fcall *fcall) if(err) return "max value out of range 0x0000..0xffff"; page[i1]->area[i2]->capacity = i; - /* TODO: detach to many clients/attach */ + match_capacity(page[i1]->area[i2]); break; case Fmode: { @@ -1202,9 +1202,9 @@ xwrite(IXPConn *c, Fcall *fcall) buf[fcall->count] = 0; mode = str2colmode(buf); if(mode == -1) - return "invalid column mode"; + return "invalid area mode"; page[i1]->area[i2]->mode = mode; - arrange_column(page[i1]->area[i2]); + arrange_area(page[i1]->area[i2]); } break; case Fkey: diff --git a/cmd/wm/wm.h b/cmd/wm/wm.h @@ -198,6 +198,13 @@ void select_area(Area *a, char *arg); void sendto_area(Area *to, Client *c); void attach_client2area(Area *a, Client *c); void detach_client_area(Client *c); +void arrange_page(Page *p, Bool update_area_geometry); +void arrange_area(Area *a); +void resize_area(Client *c, XRectangle *r, XPoint *pt); +Area *new_area(Area *old); +ColumnMode str2colmode(char *arg); +char *colmode2str(ColumnMode mode); +void match_capacity(Area *a); /* bar.c */ Label *new_label(); @@ -274,17 +281,6 @@ int pid2index(unsigned short id); void select_page(char *arg); int page2index(Page *p); -/* spawn.c */ -void spawn(char *cmd); - -/* column.c */ -void arrange_page(Page *p, Bool update_colums); -void arrange_column(Area *col); -void resize_column(Client *c, XRectangle *r, XPoint *pt); -Area *new_column(Area *old); -ColumnMode str2colmode(char *arg); -char *colmode2str(ColumnMode mode); - /* wm.c */ void scan_wins(); Client *win2client(Window w);