/* * wmfs2 by Martin Duquesnoy { for(i = 2011; i < 2111; ++i) ©(i); } * For license, see COPYING. */ #include /* 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, *l; t = xcalloc(1, sizeof(struct tag)); t->screen = s; t->flags = 0; t->id = 0; t->sel = NULL; t->prev = NULL; if((l = TAILQ_LAST(&s->tags, tsub))) t->id = l->id + 1; if(!name || !strlen(name)) xasprintf(&t->name, "%d", t->id + 1); else t->name = xstrdup(name); SLIST_INIT(&t->clients); TAILQ_INIT(&t->sets); TAILQ_INSERT_TAIL(&s->tags, t, next); return t; } void tag_screen(struct screen *s, struct tag *t) { struct client *c; /* Return to the previous tag */ if(t == s->seltag && TAILQ_NEXT(TAILQ_FIRST(&s->tags), next)) t = t->prev; if(!t) t = TAILQ_FIRST(&s->tags); /* Move clients which ignore tags */ SLIST_FOREACH(c, &W->h.client, next) if (c->flags & CLIENT_IGNORE_TAG) tag_client(t, c); t->prev = s->seltag; s->seltag = t; clients_arrange_map(); /* Update focus */ if(!SLIST_EMPTY(&t->clients) && !(W->flags & WMFS_SCAN)) client_focus( client_tab_next(t->sel)); t->flags &= ~TAG_URGENT; infobar_elem_screen_update(s, ElemTag); ewmh_update_wmfs_props(); } /* 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 && !(c->flags & CLIENT_RULED)) { if(c->tag == t) return; if(!(c->flags & (CLIENT_IGNORE_LAYOUT | CLIENT_FREE))) layout_split_arrange_closed(c); if(!(c->flags & CLIENT_REMOVEALL)) { SLIST_REMOVE(&c->tag->clients, c, client, tnext); if(c->tag->sel == c || W->client == c) client_focus( client_tab_next( client_next(c))); } } c->flags &= ~CLIENT_RULED; /* Client remove */ if(!t) { infobar_elem_screen_update(c->screen, ElemTag); return; } c->prevtag = c->tag; c->tag = t; c->screen = t->screen; client_update_props(c, CPROP_LOC); SLIST_INSERT_HEAD(&t->clients, c, tnext); infobar_elem_screen_update(c->screen, ElemTag); if(c->flags & CLIENT_TABMASTER && c->prevtag) { struct client *cc; SLIST_FOREACH(cc, &c->prevtag->clients, tnext) if(cc->tabmaster == c) { cc->flags |= CLIENT_IGNORE_LAYOUT; tag_client(t, cc); } } layout_client(c); if(t != c->screen->seltag || c->flags & CLIENT_TABBED) client_unmap(c); } 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(W->flags & WMFS_TAGCIRC) 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(W->flags & WMFS_TAGCIRC) tag_screen(W->screen, TAILQ_LAST(&W->screen->tags, tsub)); } void uicb_tag_client(Uicb cmd) { struct tag *t; int id = ATOI(cmd); if(W->client && (t = tag_gb_id(W->screen, id))) tag_client(t, W->client); } void uicb_tag_client_and_set(Uicb cmd) { uicb_tag_client(cmd); uicb_tag_set(cmd); } void uicb_tag_move_client_next(Uicb cmd) { (void)cmd; struct tag *t; if(!W->client) return; if((t = TAILQ_NEXT(W->screen->seltag, next))) tag_client(t, W->client); else if(W->flags & WMFS_TAGCIRC) tag_client(TAILQ_FIRST(&W->screen->tags), W->client); } void uicb_tag_move_client_prev(Uicb cmd) { (void)cmd; struct tag *t; if(!W->client) return; if((t = TAILQ_PREV(W->screen->seltag, tsub, next))) tag_client(t, W->client); else if(W->flags & WMFS_TAGCIRC) tag_client(TAILQ_LAST(&W->screen->tags, tsub), W->client); } void uicb_tag_click(Uicb cmd) { (void)cmd; struct tag *t; if((t = (struct tag*)W->last_clicked_barwin->ptr) && t->screen == W->screen) tag_screen(W->screen, t); } static void tag_remove(struct tag *t) { TAILQ_REMOVE(&t->screen->tags, t, next); free(t->name); layout_free_set(t); free(t); } void uicb_tag_new(Uicb cmd) { struct screen *s = W->screen; struct infobar *i; tag_new(s, (char*)cmd); s->flags |= SCREEN_TAG_UPDATE; SLIST_FOREACH(i, &s->infobars, next) infobar_elem_reinit(i); s->flags ^= SCREEN_TAG_UPDATE; } void uicb_tag_del(Uicb cmd) { struct infobar *i; struct tag *t = W->screen->seltag; (void)cmd; if(SLIST_EMPTY(&t->clients) && TAILQ_NEXT(TAILQ_FIRST(&W->screen->tags), next)) { tag_screen(W->screen, TAILQ_NEXT(t, next)); tag_remove(t); W->screen->flags |= SCREEN_TAG_UPDATE; SLIST_FOREACH(i, &W->screen->infobars, next) infobar_elem_reinit(i); W->screen->flags ^= SCREEN_TAG_UPDATE; } } void tag_free(struct screen *s) { while(!TAILQ_EMPTY(&s->tags)) tag_remove(TAILQ_FIRST(&s->tags)); }