diff --git a/src/config.c b/src/config.c index b113ddc..b0c1563 100644 --- a/src/config.c +++ b/src/config.c @@ -217,10 +217,11 @@ conf_bar_section(void) conf.bars.height = fetch_opt_first(bar, "-1", "height").num; conf.colors.bar = getcolor((barbg = fetch_opt_first(bar, "#000000", "bg").str)); conf.colors.text = fetch_opt_first(bar, "#ffffff", "fg").str; - conf.colors.bar_light_shade = fetch_opt_first(bar, "0.25", "light_shade").fnum; conf.colors.bar_dark_shade = fetch_opt_first(bar, "-0.25", "dark_shade").fnum; + conf.bars.element_order = fetch_opt_first(bar, "tls", "elements_order").str; + mouse = fetch_section(bar, "mouse"); if ((conf.bars.nmouse = fetch_section_count(mouse)) > 0) @@ -442,9 +443,6 @@ conf_layout_section(void) if((tmp = fetch_opt_first(layouts, "menu", "system").str) && !strcmp(tmp, "menu")) conf.layout_system = True; - if((tmp = fetch_opt_first(layouts, "right", "placement").str) && !strcmp(tmp, "left")) - conf.layout_placement = True; - layout = fetch_section(layouts, "layout"); conf.nlayout = fetch_section_count(layout); diff --git a/src/event.c b/src/event.c index 2a97889..ffe37a2 100644 --- a/src/event.c +++ b/src/event.c @@ -115,26 +115,29 @@ buttonpress(XEvent *e) do_mousebind(selscreen, ev->button, conf.selbar.nmouse, conf.selbar.mouse); /* Tags */ - for(i = 1; i < conf.ntag[selscreen] + 1; ++i) - if(ev->window == ib->tags[i]->win) - { - do_mousebind(selscreen, ev->button, tags[selscreen][i].nmouse, tags[selscreen][i].mouse); + if(ib->tags_board) + { + for(i = 1; i < conf.ntag[selscreen] + 1; ++i) + if(ev->window == ib->tags[i]->win) + { + do_mousebind(selscreen, ev->button, tags[selscreen][i].nmouse, tags[selscreen][i].mouse); - /* Mouse button action on tag */ - if(ev->button == conf.mouse_tag_action[TagSel]) - tag_set(i); - else if(ev->button == conf.mouse_tag_action[TagTransfert]) - tag_transfert(sel, i); - else if(ev->button == conf.mouse_tag_action[TagAdd]) - tag_additional(selscreen, seltag[selscreen], i); - else if(ev->button == conf.mouse_tag_action[TagNext]) - tag_set(seltag[selscreen] + 1); - else if(ev->button == conf.mouse_tag_action[TagPrev]) - tag_set(seltag[selscreen] - 1); - } + /* Mouse button action on tag */ + if(ev->button == conf.mouse_tag_action[TagSel]) + tag_set(i); + else if(ev->button == conf.mouse_tag_action[TagTransfert]) + tag_transfert(sel, i); + else if(ev->button == conf.mouse_tag_action[TagAdd]) + tag_additional(selscreen, seltag[selscreen], i); + else if(ev->button == conf.mouse_tag_action[TagNext]) + tag_set(seltag[selscreen] + 1); + else if(ev->button == conf.mouse_tag_action[TagPrev]) + tag_set(seltag[selscreen] - 1); + } + } /* Layout button */ - if(ev->window == ib->layout_button->win && conf.nlayout > 1) + if(ib->layout_button && ev->window == ib->layout_button->win && conf.nlayout > 1) { if(conf.layout_system && (ev->button == Button1 || ev->button == Button3)) /* True -> menu */ { diff --git a/src/infobar.c b/src/infobar.c index f05f152..7b00913 100644 --- a/src/infobar.c +++ b/src/infobar.c @@ -34,101 +34,184 @@ #define SPLIT_IND_S (3 + conf.border.layout) +/** Init InfoBar elements +*/ +static void +infobar_init_element(InfoBar *i) +{ + int j = 0, k, n = 0; + InfobarElem *e, *prev = NULL; + Geo pg = { -PAD, 0, 0, 0 }; + + STAILQ_INIT(&i->elemhead); + + for(; n < (int)strlen(i->elemorder); ++n) + { + e = zcalloc(sizeof(InfobarElem)); + + /* Previous element geo */ + if(prev) + pg = prev->geo; + + e->geo.x = pg.x + pg.width + PAD; + e->geo.y = 0; + e->geo.height = i->geo.height; + + switch(i->elemorder[n]) + { + /* Tags element */ + case 't': + e->type = ElemTag; + e->geo.width = PAD; /* Will change */ + + if(!i->tags_board) + { + i->tags_board = barwin_create(i->bar->win, + e->geo.x, + e->geo.y, + e->geo.width, + e->geo.height, + conf.colors.bar, conf.colors.text, + False, False, False); + + /* Create tags window */ + for(k = 1; k < conf.ntag[i->screen] + 1; ++k) + { + i->tags[k] = barwin_create(i->tags_board->win, + j, 0, + textw(tags[i->screen][k].name) + PAD, + i->geo.height, + conf.colors.bar, conf.colors.text, + False, False, conf.border.tag); + + j += textw(tags[i->screen][k].name) + PAD; + barwin_map_subwin(i->tags[k]); + } + } + + barwin_resize(i->tags_board, (e->geo.width = j), i->geo.height); + barwin_map(i->tags_board); + barwin_map_subwin(i->tags_board); + break; + + /* Layout button element */ + case 'l': + e->type = ElemLayout; + e->geo.width = (conf.layout_button_width > 0 + ? (uint)conf.layout_button_width + : textw(tags[i->screen][seltag[i->screen]].layout.symbol) + PAD); + + if(!i->layout_button) + i->layout_button = barwin_create(i->bar->win, + e->geo.x, + e->geo.y, + e->geo.width, + e->geo.height, + conf.colors.layout_bg, conf.colors.layout_fg, + False, False, conf.border.layout); + + barwin_map(i->layout_button); + + if(conf.border.layout) + barwin_map_subwin(i->layout_button); + break; + + /* Selbar element */ + case 's': + e->type = ElemSelbar; + i->selbar_geo = e->geo; + break; + } + + STAILQ_INSERT_TAIL(&i->elemhead, e, next); + + prev = e; + e = NULL; + } + + return; +} + /** Init the InfoBar */ void infobar_init(void) { - InfoBar *ib; - int s, sc, i, j = 0; - - s = screen_count(); + InfoBar *i; + int s = screen_count(), sc = 0; if(!infobar) infobar = xcalloc(s, sizeof(InfoBar)); - for(sc = 0; sc < s; ++sc) + for(; sc < s; ++sc) { - j = 0; - ib = &infobar[sc]; - ib->geo.height = INFOBARH; - ib->screen = sc; + i = &infobar[sc]; + i->geo.height = INFOBARH; + i->screen = sc; + i->elemorder = conf.bars.element_order; switch(tags[sc][seltag[sc]].barpos) { - case IB_Hide: - sgeo[sc].y = spgeo[sc].y + TBARH; - sgeo[sc].height += INFOBARH; - ib->geo.y = (-(ib->geo.height) << 2); - break; - case IB_Bottom: - sgeo[sc].y = TBARH; - ib->geo.y = spgeo[sc].y + sgeo[sc].height + TBARH; - break; - default: - case IB_Top: - sgeo[sc].y = spgeo[sc].y + INFOBARH + TBARH; - ib->geo.y = spgeo[sc].y; - break; + case IB_Hide: + sgeo[sc].y = spgeo[sc].y + TBARH; + sgeo[sc].height += INFOBARH; + i->geo.y = (-(i->geo.height) << 2); + break; + case IB_Bottom: + sgeo[sc].y = TBARH; + i->geo.y = spgeo[sc].y + sgeo[sc].height + TBARH; + break; + default: + case IB_Top: + sgeo[sc].y = spgeo[sc].y + INFOBARH + TBARH; + i->geo.y = spgeo[sc].y; + break; } /* Create infobar barwindow */ - ib->bar = barwin_create(ROOT, sgeo[sc].x - BORDH, ib->geo.y, - sgeo[sc].width, ib->geo.height, - conf.colors.bar, conf.colors.text, False, False, conf.border.bar); + i->bar = barwin_create(ROOT, + sgeo[sc].x - BORDH, + i->geo.y, + sgeo[sc].width, + i->geo.height, + conf.colors.bar, conf.colors.text, + False, False, conf.border.bar); - ib->tags_board = barwin_create(ib->bar->win, - ((conf.layout_placement) ? textw(tags[sc][seltag[sc]].layout.symbol) + PAD * 1.5: 0), 0, - textw(tags[sc][0].name) + PAD, /* Base size, will change */ - ib->geo.height, - conf.colors.bar, conf.colors.text, False, False, False); + barwin_map(i->bar); + barwin_map_subwin(i->bar); + barwin_refresh_color(i->bar); + barwin_refresh(i->bar); - /* Create tags window */ - for(i = 1; i < conf.ntag[sc] + 1; ++i) - { - ib->tags[i] = barwin_create(ib->tags_board->win, j, 0, - textw(tags[sc][i].name) + PAD, - ib->geo.height, - conf.colors.bar, conf.colors.text, False, False, conf.border.tag); - - j += textw(tags[sc][i].name) + PAD; - - barwin_resize(ib->tags_board, j, ib->geo.height); - barwin_map_subwin(ib->tags[i]); - } - - /* Create layout switch barwindow */ - ib->layout_button = barwin_create(ib->bar->win, - ((conf.layout_placement) ? 0 : (j + (PAD >> 1))), 0, - ((conf.layout_button_width > 0) ? (uint)conf.layout_button_width : (textw(tags[sc][seltag[sc]].layout.symbol) + PAD)), - ib->geo.height, - conf.colors.layout_bg, conf.colors.layout_fg, - False, False, conf.border.layout); - - /* Selbar */ - if(conf.bars.selbar) - { - ib->selbar_geo.y = 0; - ib->selbar_geo.height = ib->geo.height; - } - - /* Map/Refresh all */ - barwin_map(ib->bar); - barwin_map_subwin(ib->bar); - - barwin_map(ib->tags_board); - barwin_map_subwin(ib->tags_board); - - if(conf.border.layout) - barwin_map_subwin(ib->layout_button); - - barwin_refresh_color(ib->bar); - barwin_refresh(ib->bar); + /* Init elements */ + infobar_init_element(i); /* Default statustext is set here */ - ib->statustext = xstrdup("wmfs"WMFS_VERSION); + i->statustext = xstrdup("wmfs"WMFS_VERSION); - infobar_draw(ib); + infobar_draw(i); + } + + return; +} + +static void +infobar_arrange_element(InfoBar *i) +{ + Geo pg = { -PAD, 0, 0, 0 }; + InfobarElem *e, *pe = NULL; + + STAILQ_FOREACH(e, &i->elemhead, next) + { + if(pe) + pg = pe->geo; + + e->geo.x = pg.x + pg.width + PAD; + e->geo.y = 0; + + if(e->type != ElemSelbar) + barwin_move((e->type == ElemTag ? i->tags_board : i->layout_button), e->geo.x, e->geo.y); + + pe = e; } return; @@ -140,28 +223,34 @@ infobar_init(void) void infobar_draw_layout(InfoBar *i) { - int w, sc = i->screen; + InfobarElem *e; + int s = i->screen; - if(!conf.layout_placement) - barwin_move(i->layout_button, i->tags_board->geo.width + (PAD >> 1), 0); + /* Check if there is element in string element list */ + if(!strchr(i->elemorder, 'l')) + return; - w = (conf.layout_button_width >= 1) + STAILQ_FOREACH(e, &i->elemhead, next) + if(e->type == ElemLayout) + break; + + e->geo.width = (conf.layout_button_width >= 1) ? conf.layout_button_width - : (int)(textw(tags[sc][seltag[sc]].layout.symbol) + PAD); + : (int)(textw(tags[s][seltag[s]].layout.symbol) + PAD); - barwin_resize(i->layout_button, w, i->geo.height); + barwin_resize(i->layout_button, e->geo.width, e->geo.height); barwin_refresh_color(i->layout_button); /* Split mode indicator; little rectangle at bottom-right */ - if(tags[sc][seltag[sc]].flags & SplitFlag) + if(tags[s][seltag[s]].flags & SplitFlag) draw_rectangle(i->layout_button->dr, - w - SPLIT_IND_S, - i->geo.height - SPLIT_IND_S, + e->geo.width - SPLIT_IND_S, + e->geo.height - SPLIT_IND_S, SPLIT_IND_S, SPLIT_IND_S, getcolor(i->layout_button->fg)); - if(tags[sc][seltag[sc]].layout.symbol) - barwin_draw_text(i->layout_button, (PAD >> 1), FHINFOBAR, tags[sc][seltag[sc]].layout.symbol); + if(tags[s][seltag[s]].layout.symbol) + barwin_draw_text(i->layout_button, (PAD >> 1), FHINFOBAR, tags[s][seltag[s]].layout.symbol); return; } @@ -179,6 +268,8 @@ _infobar_draw(InfoBar *i) barwin_refresh(i->bar); + infobar_arrange_element(i); + return; } @@ -202,6 +293,7 @@ infobar_draw(InfoBar *i) void infobar_draw_selbar(InfoBar *i) { + InfobarElem *e; char *str = NULL; int sc = i->screen; bool f = False; @@ -209,9 +301,16 @@ infobar_draw_selbar(InfoBar *i) if(!conf.bars.selbar) return; + if(!strchr(i->elemorder, 's')) + return; + if(!sel || (sel && sel->screen != sc)) return; + STAILQ_FOREACH(e, &i->elemhead, next) + if(e->type == ElemSelbar) + break; + str = sel->title; /* Truncate string if too long */ @@ -227,17 +326,19 @@ infobar_draw_selbar(InfoBar *i) f = True; } - i->selbar_geo.x = (conf.layout_placement - ? i->tags_board->geo.x + i->tags_board->geo.width + (PAD >> 1) - : i->layout_button->geo.x + i->layout_button->geo.width + (PAD >> 1)); - XSetForeground(dpy, gc, conf.selbar.bg); - XFillRectangle(dpy, i->bar->dr, gc, i->selbar_geo.x, 0, (i->selbar_geo.width = textw(str) + PAD), i->geo.height); - draw_text(i->bar->dr, i->selbar_geo.x, FHINFOBAR - 1, conf.selbar.fg, str); + XFillRectangle(dpy, i->bar->dr, gc, + e->geo.x, + e->geo.y, + (e->geo.width = textw(str) + PAD), + e->geo.height); + draw_text(i->bar->dr, e->geo.x, FHINFOBAR, conf.selbar.fg, str); if(f) free(str); + i->selbar_geo = e->geo; + return; } @@ -247,21 +348,23 @@ infobar_draw_selbar(InfoBar *i) void infobar_draw_taglist(InfoBar *i) { - int j, x, sc = i->screen; - Client *c = SLIST_FIRST(&clients); + InfobarElem *e; + Client *c; + int j = 1, x = 0, sc = i->screen; uint occupied = 0; - if(conf.layout_placement) - barwin_move(i->tags_board, - ((conf.layout_button_width > 0) - ? (uint)conf.layout_button_width - : (textw(tags[sc][seltag[sc]].layout.symbol) + PAD)) + (PAD >> 1), 0); + if(!strchr(i->elemorder, 't')) + return; + + STAILQ_FOREACH(e, &i->elemhead, next) + if(e->type == ElemTag) + break; SLIST_FOREACH(c, &clients, next) if(c->screen == sc) occupied |= TagFlag(c->tag); - for(j = 1, x = 0; j < conf.ntag[sc] + 1; ++j) + for(; j < conf.ntag[sc] + 1; ++j) { /* Autohide tag feature */ if(conf.tagautohide) @@ -274,7 +377,7 @@ infobar_draw_taglist(InfoBar *i) barwin_map(i->tags[j]); barwin_move(i->tags[j], x, 0); - barwin_resize(i->tags_board, (x += i->tags[j]->geo.width), i->geo.height); + barwin_resize(i->tags_board, (e->geo.width = (x += i->tags[j]->geo.width)), e->geo.height); } if(tags[sc][j].flags & TagUrgentFlag) @@ -343,6 +446,7 @@ infobar_update_taglist(InfoBar *i) void infobar_destroy(void) { + InfobarElem *e; int sc, i; for(sc = 0; sc < screen_count(); ++sc) @@ -360,6 +464,15 @@ infobar_destroy(void) barwin_delete(infobar[sc].tags_board); barwin_delete_subwin(infobar[sc].bar); barwin_delete(infobar[sc].bar); + + /* Free elements */ + while(!STAILQ_EMPTY(&infobar[sc].elemhead)) + { + e = STAILQ_FIRST(&infobar[sc].elemhead); + STAILQ_REMOVE_HEAD(&infobar[sc].elemhead, next); + free(e); + } + } return; diff --git a/src/launcher.c b/src/launcher.c index 3c55a55..b603722 100644 --- a/src/launcher.c +++ b/src/launcher.c @@ -189,16 +189,17 @@ launcher_execute(Launcher *launcher) char buf[512] = { 0 }; char tmpbuf[512] = { 0 }; char *complete; - int i, pos = 0, histpos = 0, x, w; + int i, pos = 0, histpos = 0, w, x = 0; int tabhits = 0; KeySym ks; XEvent ev; + InfobarElem *e; screen_get_sel(); - x = (conf.layout_placement) - ? (infobar[selscreen].tags_board->geo.x + infobar[selscreen].tags_board->geo.width) - : (infobar[selscreen].layout_button->geo.x + infobar[selscreen].layout_button->geo.width); + STAILQ_FOREACH(e, &infobar[selscreen].elemhead, next) + if(x < (e->geo.x + e->geo.width)) + x = e->geo.x + e->geo.width + PAD; XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime); diff --git a/src/structs.h b/src/structs.h index 31f6faf..78f6e2d 100644 --- a/src/structs.h +++ b/src/structs.h @@ -112,10 +112,10 @@ enum { TagSel, TagTransfert, TagAdd, TagNext, TagPrev, TagActionLast }; /* Menu align */ enum { MA_Center = 0, MA_Left = 1, MA_Right = 2 }; -/* Infobar position */ +/* Infobar position / elements */ enum { IB_Hide = 0, IB_Bottom = 1, IB_Top = 2 }; - typedef enum { Right = 0, Left, Top, Bottom, Center, PositionLast } Position; +typedef enum { ElemTag, ElemLayout, ElemSelbar } IbElemType; /* Ewmh hints list */ enum @@ -267,12 +267,22 @@ typedef struct uicb_t cmd; } MouseBinding; +/* InfoBar elements */ +typedef struct InfobarElem +{ + IbElemType type; + Geo geo; + STAILQ_ENTRY(InfobarElem) next; +} InfobarElem; + /* InfoBar Struct */ typedef struct { - BarWindow *bar; - BarWindow *layout_button; BarWindow *tags_board, *tags[MAXTAG]; + BarWindow *layout_button; + BarWindow *bar; + STAILQ_HEAD(, InfobarElem) elemhead; + char *elemorder; Geo geo, selbar_geo; int screen, position; char *statustext; @@ -441,6 +451,7 @@ typedef struct MouseBinding *mouse; int nmouse; bool selbar; + char *element_order; } bars; struct { @@ -516,7 +527,6 @@ typedef struct bool client_auto_center; bool client_tile_raise; bool layout_system; /* Switch: False, Menu: True. */ - bool layout_placement; /* Right (normal): False, Left: True. */ bool keep_layout_geo; bool cfactor_enable_split; char *tag_expose_name; diff --git a/wmfsrc b/wmfsrc index 3534a52..edecb38 100644 --- a/wmfsrc +++ b/wmfsrc @@ -29,6 +29,12 @@ light_shade = 0.10 dark_shade = -0.10 + # Order of infobar elements: + # t = Tag list + # l = Layout button + # s = Selbar + elements_order = "tls" + [systray] # Enable/disable systray active = true @@ -65,9 +71,6 @@ # Value menu or switch. system = "menu" - # Value left or right. - placement = "right" - # Keep layout geo for free layout keep_layout_geo = false