wmfs/wmfs2/src/tag.c
Martin Duquesnoy 736b55b6c7 Minor fix
2011-09-22 01:34:36 +02:00

199 lines
4.2 KiB
C

/*
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
* For license, see COPYING.
*/
#include <X11/Xutil.h> /* IconicState / NormalState */
#include "tag.h"
#include "util.h"
#include "infobar.h"
#include "client.h"
#include "config.h"
#include "barwin.h"
#include "ewmh.h"
#include "layout.h"
struct tag*
tag_new(struct screen *s, char *name)
{
struct tag *t;
XSetWindowAttributes at =
{
.background_pixel = THEME_DEFAULT->frame_bg,
.override_redirect = true,
.background_pixmap = ParentRelative,
.event_mask = BARWIN_MASK
};
t = xcalloc(1, sizeof(struct tag));
t->screen = s;
t->name = xstrdup(name);
t->flags = 0;
t->sel = NULL;
/* Frame window */
t->frame = XCreateWindow(W->dpy, W->root,
s->ugeo.x, s->ugeo.y,
s->ugeo.w, s->ugeo.h,
0, CopyFromParent,
InputOutput,
CopyFromParent,
(CWOverrideRedirect | CWBackPixmap
| CWBackPixel | CWEventMask),
&at);
SLIST_INIT(&t->clients);
TAILQ_INSERT_TAIL(&s->tags, t, next);
return t;
}
void
tag_screen(struct screen *s, struct tag *t)
{
struct client *c;
/* Unmap previous tag's frame */
WIN_STATE(s->seltag->frame, Unmap);
SLIST_FOREACH(c, &s->seltag->clients, tnext)
ewmh_set_wm_state(c->win, IconicState);
/*
* Map selected tag's frame, only if there is
* clients in t
*/
if(!SLIST_EMPTY(&t->clients))
{
WIN_STATE(t->frame, Map);
SLIST_FOREACH(c, &t->clients, tnext)
ewmh_set_wm_state(c->win, NormalState);
client_focus(t->sel);
}
s->seltag = t;
infobar_elem_screen_update(s, ElemTag);
}
/* Set t to NULL to untag c from c->tag */
void
tag_client(struct tag *t, struct client *c)
{
/* Remove client from its previous tag */
if(c->tag)
{
if(c->tag == t)
return;
layout_split_arrange_closed(c);
SLIST_REMOVE(&c->tag->clients, c, client, tnext);
if(c->tag->sel == c || W->client == c)
client_focus(client_next(c));
}
/*
* Case of client removing: umap frame if empty
*/
if(!t)
{
/* Unmap frame if tag is now empty */
if(SLIST_EMPTY(&c->tag->clients))
WIN_STATE(c->tag->frame, Unmap);
return;
}
/* Reparent client win in frame win */
XReparentWindow(W->dpy, c->win, t->frame, 0, 0);
/* Map frame if tag was empty */
if(SLIST_EMPTY(&t->clients))
WIN_STATE(t->frame, Map);
c->tag = t;
layout_split_integrate(c, t->sel);
/* Insert in new tag list */
SLIST_INSERT_HEAD(&t->clients, c, tnext);
}
void
uicb_tag_set(Uicb cmd)
{
int i = 0, n = ATOI(cmd);
struct tag *t;
TAILQ_FOREACH(t, &W->screen->tags, next)
if(++i == n)
{
tag_screen(W->screen, t);
return;
}
}
void
uicb_tag_set_with_name(Uicb cmd)
{
struct tag *t;
TAILQ_FOREACH(t, &W->screen->tags, next)
if(!strcmp(cmd, t->name))
{
tag_screen(W->screen, t);
return;
}
}
void
uicb_tag_next(Uicb cmd)
{
(void)cmd;
struct tag *t;
if((t = TAILQ_NEXT(W->screen->seltag, next)))
tag_screen(W->screen, t);
else if( /* CIRCULAR OPTION */ 1)
tag_screen(W->screen, TAILQ_FIRST(&W->screen->tags));
}
void
uicb_tag_prev(Uicb cmd)
{
(void)cmd;
struct tag *t;
if((t = TAILQ_PREV(W->screen->seltag, tsub, next)))
tag_screen(W->screen, t);
else if( /* CIRCULAR OPTION */ 1)
tag_screen(W->screen, TAILQ_LAST(&W->screen->tags, tsub));
}
static void
tag_remove(struct tag *t)
{
free(t->name);
XDestroyWindow(W->dpy, t->frame);
free(t);
}
void
tag_free(struct screen *s)
{
struct tag *t;
TAILQ_FOREACH(t, &s->tags, next)
{
TAILQ_REMOVE(&s->tags, t, next);
tag_remove(t);
}
}