2005-11-18 18:54:58 +03:00
|
|
|
/*
|
2006-01-20 17:20:24 +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 <assert.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2005-12-27 23:13:50 +03:00
|
|
|
#include <X11/Xatom.h>
|
2005-11-18 18:54:58 +03:00
|
|
|
|
|
|
|
#include "wm.h"
|
|
|
|
|
2006-02-06 17:20:25 +03:00
|
|
|
/*
|
2006-01-26 20:29:49 +03:00
|
|
|
static void select_client(void *obj, char *arg);
|
2006-01-10 21:57:31 +03:00
|
|
|
static void xexec(void *obj, char *arg);
|
2006-01-26 20:29:49 +03:00
|
|
|
static void swap_client(void *obj, char *arg);
|
2006-02-02 15:20:07 +03:00
|
|
|
static void xnew_column(void *obj, char *arg);
|
2006-02-06 17:20:25 +03:00
|
|
|
*/
|
2005-12-12 19:04:40 +03:00
|
|
|
|
2005-12-06 01:51:01 +03:00
|
|
|
/* action table for /?/ namespace */
|
2006-02-06 17:20:25 +03:00
|
|
|
/*
|
2005-12-05 01:45:59 +03:00
|
|
|
Action page_acttbl[] = {
|
2006-01-10 21:57:31 +03:00
|
|
|
{"exec", xexec},
|
2006-01-26 20:29:49 +03:00
|
|
|
{"swap", swap_client},
|
2006-02-02 15:20:07 +03:00
|
|
|
{"newcol", xnew_column},
|
2006-01-26 20:29:49 +03:00
|
|
|
{"select", select_client},
|
2005-12-21 18:18:11 +03:00
|
|
|
{0, 0}
|
2005-11-18 18:54:58 +03:00
|
|
|
};
|
2006-02-06 17:20:25 +03:00
|
|
|
*/
|
2005-11-18 18:54:58 +03:00
|
|
|
|
2005-12-21 18:18:11 +03:00
|
|
|
Page *
|
|
|
|
alloc_page()
|
2005-11-18 18:54:58 +03:00
|
|
|
{
|
2006-02-03 20:11:22 +03:00
|
|
|
static unsigned short id = 1;
|
2006-01-26 21:58:30 +03:00
|
|
|
Page *p = cext_emallocz(sizeof(Page));
|
2006-02-02 15:20:07 +03:00
|
|
|
Area *a = cext_emallocz(sizeof(Area));
|
2005-12-21 18:18:11 +03:00
|
|
|
|
2006-02-03 18:15:36 +03:00
|
|
|
p->id = id++;
|
2006-02-02 15:20:07 +03:00
|
|
|
p->area = (Area **)cext_array_attach((void **)p->area, a, sizeof(Area *), &p->areasz);
|
|
|
|
p->narea++;
|
|
|
|
do_pend_fcall("NewPage\n");
|
2006-01-29 15:41:16 +03:00
|
|
|
page = (Page **)cext_array_attach((void **)page, p, sizeof(Page *), &pagesz);
|
2006-02-02 15:20:07 +03:00
|
|
|
npage++;
|
2006-01-26 21:58:30 +03:00
|
|
|
focus_page(p);
|
2006-01-21 20:01:28 +03:00
|
|
|
XChangeProperty(dpy, root, net_atoms[NET_NUMBER_OF_DESKTOPS], XA_CARDINAL,
|
2006-02-02 15:20:07 +03:00
|
|
|
32, PropModeReplace, (unsigned char *) &npage, 1);
|
2006-01-26 21:58:30 +03:00
|
|
|
return p;
|
2005-11-18 18:54:58 +03:00
|
|
|
}
|
|
|
|
|
2005-12-21 18:18:11 +03:00
|
|
|
void
|
2006-01-26 16:16:04 +03:00
|
|
|
destroy_page(Page *p)
|
2005-12-05 03:36:39 +03:00
|
|
|
{
|
2006-01-26 16:16:04 +03:00
|
|
|
unsigned int i;
|
|
|
|
size_t naqueue = 0;
|
2006-01-24 02:01:17 +03:00
|
|
|
|
2006-02-02 15:20:07 +03:00
|
|
|
for(i = 0; (i < aqsz) && aq[i]; i++)
|
|
|
|
if(aq[i] == p)
|
2006-01-26 16:16:04 +03:00
|
|
|
naqueue++;
|
|
|
|
for(i = 0; i < naqueue; i++)
|
2006-02-02 15:20:07 +03:00
|
|
|
cext_array_detach((void **)aq, p, &aqsz);
|
2006-01-10 21:57:31 +03:00
|
|
|
|
2006-02-03 18:15:36 +03:00
|
|
|
for(i = 0; i < p->narea; i++)
|
|
|
|
destroy_area(p->area[i]);
|
|
|
|
free(p->area);
|
2006-01-26 16:16:04 +03:00
|
|
|
|
2006-02-02 15:20:07 +03:00
|
|
|
for(i = 0; (i < npage) && (p != page[i]); i++);
|
|
|
|
if(sel && (sel == i))
|
|
|
|
sel--;
|
2005-12-27 23:13:50 +03:00
|
|
|
free(p);
|
2006-02-02 15:20:07 +03:00
|
|
|
npage--;
|
2005-12-27 23:13:50 +03:00
|
|
|
|
2006-02-02 15:20:07 +03:00
|
|
|
for(i = 0; i < npage; i++);
|
2006-01-21 20:01:28 +03:00
|
|
|
XChangeProperty(dpy, root, net_atoms[NET_NUMBER_OF_DESKTOPS], XA_CARDINAL,
|
2006-01-26 16:16:04 +03:00
|
|
|
32, PropModeReplace, (unsigned char *) &i, 1);
|
2006-01-23 18:06:14 +03:00
|
|
|
|
|
|
|
/* determine what to focus and do that */
|
2006-02-02 15:20:07 +03:00
|
|
|
if(page[sel])
|
|
|
|
focus_page(page[sel]);
|
2006-02-08 20:35:40 +03:00
|
|
|
else
|
2006-02-02 15:20:07 +03:00
|
|
|
do_pend_fcall("NoPage\n");
|
2005-11-18 18:54:58 +03:00
|
|
|
}
|
|
|
|
|
2005-12-21 18:18:11 +03:00
|
|
|
void
|
2006-01-26 16:16:04 +03:00
|
|
|
focus_page(Page *p)
|
2005-12-05 03:36:39 +03:00
|
|
|
{
|
2006-01-26 21:58:30 +03:00
|
|
|
size_t i;
|
2006-02-02 15:20:07 +03:00
|
|
|
Page *old = page ? page[sel] : nil;
|
2006-01-18 19:45:27 +03:00
|
|
|
|
2006-01-26 17:24:34 +03:00
|
|
|
if(!page)
|
2006-01-26 16:16:04 +03:00
|
|
|
return;
|
|
|
|
|
2006-02-02 15:20:07 +03:00
|
|
|
for(i = 0; (i < npage) && (page[i] != p); i++);
|
|
|
|
if(i == sel)
|
2006-01-26 16:16:04 +03:00
|
|
|
return;
|
2006-01-23 18:06:14 +03:00
|
|
|
|
2006-02-02 15:20:07 +03:00
|
|
|
sel = i;
|
|
|
|
for(i = 0; i < nclient; i++) {
|
2006-01-26 21:58:30 +03:00
|
|
|
Client *c = client[i];
|
|
|
|
if(old && (c->page == old))
|
|
|
|
XMoveWindow(dpy, c->frame.win, 2 * rect.width, 2 * rect.height);
|
2006-02-08 20:33:01 +03:00
|
|
|
else if(c->page == p) {
|
2006-01-26 21:58:30 +03:00
|
|
|
XMoveWindow(dpy, c->frame.win, c->frame.rect.x, c->frame.rect.y);
|
2006-02-08 20:33:01 +03:00
|
|
|
draw_client(c);
|
|
|
|
}
|
2006-01-26 16:16:04 +03:00
|
|
|
}
|
2006-02-02 15:20:07 +03:00
|
|
|
do_pend_fcall("SelPage\n");
|
2006-01-12 20:03:49 +03:00
|
|
|
XChangeProperty(dpy, root, net_atoms[NET_CURRENT_DESKTOP], XA_CARDINAL,
|
2006-02-02 15:20:07 +03:00
|
|
|
32, PropModeReplace, (unsigned char *) &sel, 1);
|
2006-02-04 21:55:37 +03:00
|
|
|
XSync(dpy, False);
|
2005-12-07 03:37:37 +03:00
|
|
|
}
|
|
|
|
|
2005-12-21 18:18:11 +03:00
|
|
|
XRectangle *
|
|
|
|
rectangles(unsigned int *num)
|
2005-11-18 18:54:58 +03:00
|
|
|
{
|
2005-12-21 18:18:11 +03:00
|
|
|
XRectangle *result = 0;
|
|
|
|
int i, j = 0;
|
|
|
|
Window d1, d2;
|
|
|
|
Window *wins;
|
|
|
|
XWindowAttributes wa;
|
|
|
|
XRectangle r;
|
|
|
|
|
|
|
|
if(XQueryTree(dpy, root, &d1, &d2, &wins, num)) {
|
|
|
|
result = cext_emallocz(*num * sizeof(XRectangle));
|
|
|
|
for(i = 0; i < *num; i++) {
|
|
|
|
if(!XGetWindowAttributes(dpy, wins[i], &wa))
|
|
|
|
continue;
|
|
|
|
if(wa.override_redirect && (wa.map_state == IsViewable)) {
|
|
|
|
r.x = wa.x;
|
|
|
|
r.y = wa.y;
|
|
|
|
r.width = wa.width;
|
|
|
|
r.height = wa.height;
|
|
|
|
result[j++] = r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-02-03 13:36:47 +03:00
|
|
|
if(wins)
|
2005-12-21 18:18:11 +03:00
|
|
|
XFree(wins);
|
|
|
|
*num = j;
|
|
|
|
return result;
|
2005-11-18 18:54:58 +03:00
|
|
|
}
|
|
|
|
|
2006-02-06 17:20:25 +03:00
|
|
|
/*
|
2006-01-10 21:57:31 +03:00
|
|
|
static void
|
|
|
|
xexec(void *obj, char *arg)
|
|
|
|
{
|
2006-02-02 15:20:07 +03:00
|
|
|
aq = (Page **)cext_array_attach((void **)aq, obj,
|
|
|
|
sizeof(Page *), &aqsz);
|
2006-01-10 21:57:31 +03:00
|
|
|
wmii_spawn(dpy, arg);
|
|
|
|
}
|
2006-02-06 17:20:25 +03:00
|
|
|
*/
|
2006-01-10 21:57:31 +03:00
|
|
|
|
2006-02-06 17:20:25 +03:00
|
|
|
/*
|
2006-01-26 20:29:49 +03:00
|
|
|
static void
|
|
|
|
swap_client(void *obj, char *arg)
|
|
|
|
{
|
|
|
|
Page *p = obj;
|
|
|
|
Client *c = sel_client_of_page(p);
|
2006-02-01 18:27:53 +03:00
|
|
|
Area *west = nil, *east = nil, *col = c->area;
|
2006-01-26 20:29:49 +03:00
|
|
|
Client *north = nil, *south = nil;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if(!col || !arg)
|
|
|
|
return;
|
|
|
|
|
2006-02-02 15:20:07 +03:00
|
|
|
for(i = 1; i < p->narea && (p->area[i] != col); i++);
|
2006-02-01 18:27:53 +03:00
|
|
|
west = i ? p->area[i - 1] : nil;
|
|
|
|
east = (i < p->areasz) && p->area[i + 1] ? p->area[i + 1] : nil;
|
2006-01-26 20:29:49 +03:00
|
|
|
|
2006-02-02 15:20:07 +03:00
|
|
|
for(i = 0; (i < col->nclient) && (col->client[i] != c); i++);
|
2006-01-26 20:29:49 +03:00
|
|
|
north = i ? col->client[i - 1] : nil;
|
2006-02-02 15:20:07 +03:00
|
|
|
south = (i + 1 < col->nclient) ? col->client[i + 1] : nil;
|
2006-01-26 20:29:49 +03:00
|
|
|
|
|
|
|
if(!strncmp(arg, "north", 6) && north) {
|
|
|
|
col->client[i] = col->client[i - 1];
|
|
|
|
col->client[i - 1] = c;
|
2006-02-02 15:20:07 +03:00
|
|
|
arrange_column(p, col);
|
2006-01-26 20:29:49 +03:00
|
|
|
} else if(!strncmp(arg, "south", 6) && south) {
|
|
|
|
col->client[i] = col->client[i + 1];
|
|
|
|
col->client[i + 1] = c;
|
2006-02-02 15:20:07 +03:00
|
|
|
arrange_column(p, col);
|
2006-01-26 20:29:49 +03:00
|
|
|
}
|
|
|
|
else if(!strncmp(arg, "west", 5) && west) {
|
|
|
|
col->client[i] = west->client[west->sel];
|
|
|
|
west->client[west->sel] = c;
|
2006-02-01 18:27:53 +03:00
|
|
|
west->client[west->sel]->area = west;
|
2006-02-02 15:20:07 +03:00
|
|
|
col->client[i]->area = col;
|
|
|
|
arrange_column(p, col);
|
|
|
|
arrange_column(p, west);
|
2006-01-26 20:29:49 +03:00
|
|
|
} else if(!strncmp(arg, "east", 5) && east) {
|
|
|
|
col->client[i] = west->client[west->sel];
|
2006-02-01 18:27:53 +03:00
|
|
|
col->client[i]->area = col;
|
2006-01-26 20:29:49 +03:00
|
|
|
east->client[east->sel] = c;
|
2006-02-01 18:27:53 +03:00
|
|
|
east->client[east->sel]->area = east;
|
2006-02-02 15:20:07 +03:00
|
|
|
arrange_column(p, col);
|
|
|
|
arrange_column(p, east);
|
2006-01-26 20:29:49 +03:00
|
|
|
}
|
|
|
|
focus_client(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-02-02 15:20:07 +03:00
|
|
|
xnew_column(void *obj, char *arg)
|
2006-01-26 20:29:49 +03:00
|
|
|
{
|
2006-02-02 15:20:07 +03:00
|
|
|
new_column(obj);
|
2006-01-26 20:29:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
select_client(void *obj, char *arg)
|
|
|
|
{
|
|
|
|
Page *p = obj;
|
|
|
|
Client *c = sel_client_of_page(p);
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if(!c || !arg)
|
|
|
|
return;
|
|
|
|
|
2006-02-02 15:20:07 +03:00
|
|
|
if(index_of_area(c->page, c->area) > 0)
|
|
|
|
select_column(c, arg);
|
2006-01-26 20:29:49 +03:00
|
|
|
else {
|
2006-02-02 15:20:07 +03:00
|
|
|
Area *a = c->area;
|
|
|
|
for(i = 0; (i < a->nclient) && (a->client[i] != c); i++);
|
2006-01-26 20:29:49 +03:00
|
|
|
if(!strncmp(arg, "prev", 5)) {
|
|
|
|
if(!i)
|
2006-02-02 15:20:07 +03:00
|
|
|
i = a->nclient - 1;
|
|
|
|
focus_client(a->client[i]);
|
2006-01-26 20:29:49 +03:00
|
|
|
} else if(!strncmp(arg, "next", 5)) {
|
2006-02-02 15:20:07 +03:00
|
|
|
if(i + 1 < a->nclient)
|
|
|
|
focus_client(a->client[i + 1]);
|
2006-01-26 20:29:49 +03:00
|
|
|
else
|
2006-02-02 15:20:07 +03:00
|
|
|
focus_client(a->client[0]);
|
2006-01-26 20:29:49 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
const char *errstr;
|
2006-02-02 15:20:07 +03:00
|
|
|
i = cext_strtonum(arg, 0, a->nclient - 1, &errstr);
|
2006-01-26 20:29:49 +03:00
|
|
|
if(errstr)
|
|
|
|
return;
|
2006-02-02 15:20:07 +03:00
|
|
|
focus_client(a->client[i]);
|
2006-01-26 20:29:49 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-02-06 17:20:25 +03:00
|
|
|
*/
|
2006-01-26 20:29:49 +03:00
|
|
|
|
2006-02-02 15:20:07 +03:00
|
|
|
int
|
2006-02-03 18:15:36 +03:00
|
|
|
index_of_page_id(unsigned short id)
|
2006-02-02 15:20:07 +03:00
|
|
|
{
|
|
|
|
int i;
|
2006-02-03 18:15:36 +03:00
|
|
|
if(id == NEW_OBJ)
|
|
|
|
return npage;
|
|
|
|
for(i = 0; i < npage; i++)
|
|
|
|
if(page[i]->id == id)
|
2006-02-02 15:20:07 +03:00
|
|
|
return i;
|
|
|
|
return -1;
|
|
|
|
}
|