wmii/cmd/wm/page.c

256 lines
6.2 KiB
C
Raw Normal View History

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"
2005-12-21 18:18:11 +03:00
static void handle_after_write_page(IXPServer * s, File * file);
2005-11-18 18:54:58 +03:00
2006-01-12 18:06:50 +03:00
static void toggle_layout(void *obj, char *arg);
static void xexec(void *obj, char *arg);
2005-12-12 19:04:40 +03:00
/* action table for /?/ namespace */
2005-12-05 01:45:59 +03:00
Action page_acttbl[] = {
2006-01-12 18:06:50 +03:00
{"toggle", toggle_layout},
{"exec", xexec},
2005-12-21 18:18:11 +03:00
{0, 0}
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
{
2005-12-21 18:18:11 +03:00
Page *p, *new = cext_emallocz(sizeof(Page));
char buf[MAX_BUF], buf2[16];
snprintf(buf2, sizeof(buf2), "%d", pageid);
snprintf(buf, sizeof(buf), "/%d", pageid);
2005-12-21 18:18:11 +03:00
new->file[P_PREFIX] = ixp_create(ixps, buf);
snprintf(buf, sizeof(buf), "/%d/name", pageid);
2005-12-21 18:18:11 +03:00
new->file[P_NAME] = wmii_create_ixpfile(ixps, buf, buf2);
snprintf(buf, sizeof(buf), "/%d/layout/", pageid);
2006-01-12 18:44:06 +03:00
new->file[P_LAYOUT_PREFIX] = ixp_create(ixps, buf);
snprintf(buf, sizeof(buf), "/%d/layout/sel", pageid);
2006-01-12 18:44:06 +03:00
new->file[P_SEL_LAYOUT] = ixp_create(ixps, buf);
new->file[P_SEL_LAYOUT]->bind = 1; /* mount point */
snprintf(buf, MAX_BUF, "/%d/layoutname", pageid);
new->file[P_LAYOUT_NAME] = wmii_create_ixpfile(ixps, buf, def[WM_LAYOUT]->content);
new->file[P_LAYOUT_NAME]->after_write = handle_after_write_page;
snprintf(buf, sizeof(buf), "/%d/ctl", pageid);
2005-12-21 18:18:11 +03:00
new->file[P_CTL] = ixp_create(ixps, buf);
new->file[P_CTL]->after_write = handle_after_write_page;
new->floating = alloc_layout(new, LAYOUT_FLOAT);
2006-01-12 18:06:50 +03:00
new->sel = new->managed = alloc_layout(new, def[WM_LAYOUT]->content);
2005-12-21 18:18:11 +03:00
for(p = pages; p && p->next; p = p->next);
2005-12-27 23:13:50 +03:00
if(!p) {
2005-12-21 18:18:11 +03:00
pages = new;
2005-12-27 23:13:50 +03:00
new->index = 0;
}
2005-12-21 18:18:11 +03:00
else {
new->prev = p;
p->next = new;
2005-12-27 23:13:50 +03:00
new->index = p->index + 1;
2005-12-21 18:18:11 +03:00
}
def[WM_SEL_PAGE]->content = new->file[P_PREFIX]->content;
invoke_wm_event(def[WM_EVENT_PAGE_UPDATE]);
pageid++;
2005-12-21 18:18:11 +03:00
npages++;
2005-12-27 23:13:50 +03:00
XChangeProperty(dpy, root, net_atoms[NET_NUMBER_OF_DESKTOPS], XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &npages, 1);
2005-12-21 18:18:11 +03:00
return new;
2005-11-18 18:54:58 +03:00
}
2005-12-21 18:18:11 +03:00
void
destroy_page(Page * p)
{
AttachQueue *o, *n;
while(attachqueue && (attachqueue->page == p)) {
n = attachqueue->next;
free(attachqueue);
attachqueue = n;
}
o = attachqueue;
n = nil;
if(attachqueue)
n = attachqueue->next;
while(n) {
if(n->page == p) {
o->next = n->next;
free(n);
n = o->next;
}
else
n = n->next;
}
2006-01-12 18:06:50 +03:00
destroy_layout(p->floating);
destroy_layout(p->managed);
2005-12-21 18:18:11 +03:00
def[WM_SEL_PAGE]->content = 0;
ixp_remove_file(ixps, p->file[P_PREFIX]);
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;
2005-12-27 23:13:50 +03:00
pages->index = 0;
2005-12-21 18:18:11 +03:00
} else {
p->prev->next = p->next;
if(p->next)
p->next->prev = p->prev;
}
2005-12-27 23:13:50 +03:00
free(p);
/* update page indexes */
for (p = pages; p && p->next; p = p->next) {
if (p->prev && p->prev->index + 1 != p->index) /* if page index difference is not one */
--(p->index);
}
2005-12-21 18:18:11 +03:00
if(!selpage)
selpage = pages;
npages--;
2005-12-27 23:13:50 +03:00
XChangeProperty(dpy, root, net_atoms[NET_NUMBER_OF_DESKTOPS], XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &npages, 1);
2005-11-18 18:54:58 +03:00
}
2005-12-21 18:18:11 +03:00
void
focus_page(Page * p)
{
if(!p)
return;
if((p != selpage)) {
2006-01-17 19:01:35 +03:00
if(selpage) {
unmap_layout(selpage->managed);
unmap_layout(selpage->floating);
}
}
if(p != selpage) {
map_layout(p->managed, False);
map_layout(p->floating, False);
}
2005-12-21 18:18:11 +03:00
selpage = p;
def[WM_SEL_PAGE]->content = p->file[P_PREFIX]->content;
invoke_wm_event(def[WM_EVENT_PAGE_UPDATE]);
2006-01-17 19:01:35 +03:00
focus_layout(p->sel);
XChangeProperty(dpy, root, net_atoms[NET_CURRENT_DESKTOP], XA_CARDINAL,
32, PropModeReplace, (unsigned char *) &(selpage->index), 1);
}
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;
}
}
}
if(wins) {
XFree(wins);
}
*num = j;
return result;
2005-11-18 18:54:58 +03:00
}
2005-12-21 18:18:11 +03:00
static void
handle_after_write_page(IXPServer * s, File * file)
2005-11-18 18:54:58 +03:00
{
2005-12-21 18:18:11 +03:00
Page *p;
for(p = pages; p; p = p->next) {
if(file == p->file[P_CTL]) {
run_action(file, p, page_acttbl);
return;
}
else if(file == p->file[P_LAYOUT_NAME]) {
LayoutDef *l = match_layout_def(file->content);
Client *clients = nil;
if(!strncmp(file->content, LAYOUT_FLOAT, strlen(LAYOUT_FLOAT)))
l = nil;
if(p->managed->def)
clients = p->managed->def->deinit(p->managed);
p->managed->def = l;
if(l) {
p->managed->def->init(p->managed, clients);
focus_layout(p->managed);
}
else {
Client *n;
focus_layout(p->floating);
while(clients) {
n = clients->next;
p->floating->def->attach(p->floating, clients);
clients = n;
}
}
invoke_wm_event(def[WM_EVENT_PAGE_UPDATE]);
2005-12-21 18:18:11 +03:00
}
}
2005-11-18 18:54:58 +03:00
}
static void
xexec(void *obj, char *arg)
{
AttachQueue *r;
if(!attachqueue)
r = attachqueue = cext_emallocz(sizeof(AttachQueue));
else {
for(r = attachqueue; r && r->next; r = r->next);
r->next = cext_emallocz(sizeof(AttachQueue));
r = r->next;
}
r->page = obj;
wmii_spawn(dpy, arg);
}
2005-12-21 18:18:11 +03:00
static void
2006-01-12 18:06:50 +03:00
toggle_layout(void *obj, char *arg)
2005-11-18 18:54:58 +03:00
{
2005-12-21 18:18:11 +03:00
Page *p = obj;
2006-01-19 20:55:08 +03:00
if(!p->managed->def || (p->sel == p->managed))
focus_layout(p->floating);
2005-12-21 18:18:11 +03:00
else
2006-01-19 20:55:08 +03:00
focus_layout(p->managed);
}
2005-12-12 19:04:40 +03:00
2005-12-21 18:18:11 +03:00
Page *
pageat(unsigned int idx)
2005-12-12 19:04:40 +03:00
{
2005-12-21 18:18:11 +03:00
unsigned int i = 0;
Page *p;
for(p = pages; p && i != idx; p = p->next)
i++;
2005-12-21 18:18:11 +03:00
return p;
2005-12-12 19:04:40 +03:00
}