2005-11-18 18:54:58 +03:00
|
|
|
/*
|
2006-01-13 15:24:55 +03:00
|
|
|
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
2005-11-18 18:54:58 +03:00
|
|
|
* See LICENSE file for license details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "wm.h"
|
|
|
|
|
2006-03-01 09:51:04 +03:00
|
|
|
ColumnMode
|
|
|
|
str2colmode(char *arg)
|
|
|
|
{
|
|
|
|
if(!strncmp("equal", arg, 6))
|
|
|
|
return COL_EQUAL;
|
|
|
|
else if(!strncmp("stack", arg, 6))
|
|
|
|
return COL_STACK;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2006-01-26 20:29:49 +03:00
|
|
|
void
|
2006-02-19 17:40:44 +03:00
|
|
|
arrange_column(Area *col)
|
2005-12-07 03:37:37 +03:00
|
|
|
{
|
2006-02-28 19:13:16 +03:00
|
|
|
size_t i, yoff;
|
2006-01-26 17:24:34 +03:00
|
|
|
unsigned int h;
|
|
|
|
|
2006-03-01 10:59:42 +03:00
|
|
|
if(!col->nclient)
|
|
|
|
return;
|
|
|
|
|
2006-02-28 19:13:16 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2006-01-26 17:24:34 +03:00
|
|
|
}
|
2005-12-07 03:37:37 +03:00
|
|
|
}
|
|
|
|
|
2006-01-26 17:24:34 +03:00
|
|
|
void
|
2006-02-19 17:40:44 +03:00
|
|
|
arrange_page(Page *p, Bool update_colums)
|
2005-12-13 18:10:22 +03:00
|
|
|
{
|
2006-01-26 17:24:34 +03:00
|
|
|
size_t i;
|
2006-02-19 17:56:16 +03:00
|
|
|
unsigned int width;
|
2006-01-26 17:24:34 +03:00
|
|
|
|
2006-02-02 15:20:07 +03:00
|
|
|
if(p->narea == 1)
|
2006-01-26 17:24:34 +03:00
|
|
|
return;
|
2006-02-19 17:40:44 +03:00
|
|
|
|
2006-02-19 17:56:16 +03:00
|
|
|
width = rect.width / (p->narea - 1);
|
|
|
|
for(i = 1; i < p->narea; i++) {
|
|
|
|
Area *a = p->area[i];
|
|
|
|
if(update_colums) {
|
2006-02-19 18:21:01 +03:00
|
|
|
update_area_geometry(a);
|
2006-02-19 17:56:16 +03:00
|
|
|
a->rect.x = (i - 1) * width;
|
|
|
|
a->rect.width = width;
|
2006-02-19 17:40:44 +03:00
|
|
|
}
|
2006-02-19 17:56:16 +03:00
|
|
|
arrange_column(a);
|
2006-01-19 20:36:20 +03:00
|
|
|
}
|
2006-02-19 17:40:44 +03:00
|
|
|
}
|
2005-11-18 18:54:58 +03:00
|
|
|
|
2005-12-21 18:18:11 +03:00
|
|
|
static void
|
2006-02-02 15:20:07 +03:00
|
|
|
match_horiz(Area *col, XRectangle *r)
|
2005-11-18 18:54:58 +03:00
|
|
|
{
|
2006-01-26 17:24:34 +03:00
|
|
|
size_t i;
|
|
|
|
|
2006-02-24 12:06:02 +03:00
|
|
|
for(i = 0; i < col->nclient; i++) {
|
2006-01-26 17:24:34 +03:00
|
|
|
Client *c = col->client[i];
|
|
|
|
c->frame.rect.x = r->x;
|
|
|
|
c->frame.rect.width = r->width;
|
|
|
|
resize_client(c, &c->frame.rect, nil);
|
2005-12-21 18:18:11 +03:00
|
|
|
}
|
2005-12-10 18:38:43 +03:00
|
|
|
}
|
2005-11-18 18:54:58 +03:00
|
|
|
|
2005-12-21 18:18:11 +03:00
|
|
|
static void
|
2006-01-26 17:24:34 +03:00
|
|
|
drop_resize(Client *c, XRectangle *new)
|
2005-12-10 18:38:43 +03:00
|
|
|
{
|
2006-02-02 15:20:07 +03:00
|
|
|
Area *west = nil, *east = nil, *col = c->area;
|
2006-02-11 17:22:42 +03:00
|
|
|
Page *p = col->page;
|
2006-01-26 17:24:34 +03:00
|
|
|
Client *north = nil, *south = nil;
|
|
|
|
size_t i;
|
2005-12-21 18:18:11 +03:00
|
|
|
|
2006-02-02 15:20:07 +03:00
|
|
|
for(i = 0; (i < p->narea) && (p->area[i] != col); i++);
|
|
|
|
west = i ? p->area[i - 1] : nil;
|
2006-02-24 12:06:02 +03:00
|
|
|
east = i + 1 < p->narea ? p->area[i + 1] : nil;
|
2006-01-26 17:24:34 +03:00
|
|
|
|
2006-02-24 12:06:02 +03:00
|
|
|
for(i = 0; (i < col->nclient) && (col->client[i] != c); i++);
|
2006-01-26 17:24:34 +03:00
|
|
|
north = i ? col->client[i - 1] : nil;
|
2006-02-24 12:06:02 +03:00
|
|
|
south = i + 1 < col->nclient ? col->client[i + 1] : nil;
|
2005-12-21 18:18:11 +03:00
|
|
|
|
|
|
|
/* horizontal resize */
|
2006-01-26 17:24:34 +03:00
|
|
|
if(west && (new->x != c->frame.rect.x)) {
|
2005-12-21 18:18:11 +03:00
|
|
|
west->rect.width = new->x - west->rect.x;
|
2006-01-26 17:24:34 +03:00
|
|
|
col->rect.width += c->frame.rect.x - new->x;
|
|
|
|
col->rect.x = new->x;
|
|
|
|
match_horiz(west, &west->rect);
|
|
|
|
match_horiz(col, &col->rect);
|
2005-12-21 18:18:11 +03:00
|
|
|
}
|
2006-01-26 17:24:34 +03:00
|
|
|
if(east && (new->x + new->width != c->frame.rect.x + c->frame.rect.width)) {
|
2005-12-21 18:18:11 +03:00
|
|
|
east->rect.width -= new->x + new->width - east->rect.x;
|
|
|
|
east->rect.x = new->x + new->width;
|
2006-01-26 17:24:34 +03:00
|
|
|
col->rect.x = new->x;
|
|
|
|
col->rect.width = new->width;
|
|
|
|
match_horiz(col, &col->rect);
|
|
|
|
match_horiz(east, &east->rect);
|
2005-12-21 18:18:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* vertical resize */
|
2006-01-26 17:24:34 +03:00
|
|
|
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);
|
|
|
|
resize_client(c, &c->frame.rect, nil);
|
2005-12-21 18:18:11 +03:00
|
|
|
}
|
2006-01-26 17:24:34 +03:00
|
|
|
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);
|
|
|
|
resize_client(south, &south->frame.rect, nil);
|
2005-12-21 18:18:11 +03:00
|
|
|
}
|
2005-11-18 18:54:58 +03:00
|
|
|
}
|
|
|
|
|
2005-12-21 18:18:11 +03:00
|
|
|
static void
|
2006-01-26 17:24:34 +03:00
|
|
|
drop_moving(Client *c, XRectangle *new, XPoint * pt)
|
2005-11-18 18:54:58 +03:00
|
|
|
{
|
2006-02-02 15:20:07 +03:00
|
|
|
Area *tgt = nil, *src = c->area;
|
2006-02-11 17:22:42 +03:00
|
|
|
Page *p = src->page;
|
2006-01-26 17:24:34 +03:00
|
|
|
size_t i;
|
2005-12-21 18:18:11 +03:00
|
|
|
|
2006-02-24 12:06:02 +03:00
|
|
|
if(!pt || src->nclient < 2)
|
2005-12-21 18:18:11 +03:00
|
|
|
return;
|
|
|
|
|
2006-02-24 12:06:02 +03:00
|
|
|
for(i = 1; (i < p->narea) &&
|
2006-02-02 15:20:07 +03:00
|
|
|
!blitz_ispointinrect(pt->x, pt->y, &p->area[i]->rect); i++);
|
2006-02-24 12:06:02 +03:00
|
|
|
if((tgt = ((i < p->narea) ? p->area[i] : nil))) {
|
|
|
|
if(tgt != src)
|
|
|
|
sendto_area(tgt, c);
|
|
|
|
else {
|
|
|
|
for(i = 0; (i < src->nclient) &&
|
2006-01-26 17:24:34 +03:00
|
|
|
!blitz_ispointinrect(pt->x, pt->y, &src->client[i]->frame.rect); i++);
|
2006-02-24 12:06:02 +03:00
|
|
|
if((i < src->nclient) && (c != src->client[i])) {
|
2006-03-01 09:51:04 +03:00
|
|
|
size_t j = client2index(c);
|
2006-02-24 12:06:02 +03:00
|
|
|
Client *tmp = src->client[j];
|
2006-01-26 17:24:34 +03:00
|
|
|
src->client[j] = src->client[i];
|
2006-02-24 12:06:02 +03:00
|
|
|
src->client[i] = tmp;
|
2006-02-19 17:40:44 +03:00
|
|
|
arrange_column(src);
|
2006-02-28 10:51:53 +03:00
|
|
|
focus_client(c);
|
2005-12-21 18:18:11 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-11-18 18:54:58 +03:00
|
|
|
}
|
|
|
|
|
2006-01-26 17:24:34 +03:00
|
|
|
void
|
|
|
|
resize_column(Client *c, XRectangle *r, XPoint *pt)
|
2005-11-18 18:54:58 +03:00
|
|
|
{
|
2006-01-26 17:24:34 +03:00
|
|
|
if((c->frame.rect.width == r->width)
|
|
|
|
&& (c->frame.rect.height == r->height))
|
|
|
|
drop_moving(c, r, pt);
|
2005-12-21 18:18:11 +03:00
|
|
|
else
|
2006-01-26 17:24:34 +03:00
|
|
|
drop_resize(c, r);
|
2005-11-18 18:54:58 +03:00
|
|
|
}
|
2005-12-09 04:46:59 +03:00
|
|
|
|
2006-02-19 17:56:16 +03:00
|
|
|
Area *
|
|
|
|
new_column(Area *old)
|
2005-12-11 20:00:27 +03:00
|
|
|
{
|
2006-02-19 17:56:16 +03:00
|
|
|
Page *p = old->page;
|
2006-01-26 20:29:49 +03:00
|
|
|
Client *c = sel_client_of_page(p);
|
2006-02-19 17:56:16 +03:00
|
|
|
Area *col;
|
2005-12-16 19:18:00 +03:00
|
|
|
|
2006-03-01 09:51:04 +03:00
|
|
|
if(!area2index(old) || (old->nclient < 2))
|
2006-02-19 17:56:16 +03:00
|
|
|
return nil;
|
2005-12-16 19:18:00 +03:00
|
|
|
|
2006-02-19 17:56:16 +03:00
|
|
|
col = alloc_area(p);
|
2006-01-29 15:41:16 +03:00
|
|
|
cext_array_detach((void **)old->client, c, &old->clientsz);
|
2006-02-19 17:56:16 +03:00
|
|
|
old->nclient--;
|
2006-02-19 18:21:01 +03:00
|
|
|
if(old->sel == old->nclient)
|
|
|
|
old->sel = 0;
|
2006-01-29 15:41:16 +03:00
|
|
|
col->client = (Client **)cext_array_attach((void **)col->client, c,
|
|
|
|
sizeof(Client *), &col->clientsz);
|
2006-02-19 17:56:16 +03:00
|
|
|
col->nclient++;
|
|
|
|
|
2006-02-02 15:20:07 +03:00
|
|
|
c->area = col;
|
2006-02-19 17:40:44 +03:00
|
|
|
arrange_page(p, True);
|
2006-02-28 10:51:53 +03:00
|
|
|
focus_client(c);
|
2006-02-19 17:56:16 +03:00
|
|
|
return col;
|
2006-01-10 19:18:09 +03:00
|
|
|
}
|