diff --git a/awesome-menu.c b/awesome-menu.c index f50566b32..821b4e830 100644 --- a/awesome-menu.c +++ b/awesome-menu.c @@ -434,8 +434,8 @@ redraw(void) draw_text(globalconf.ctx, geometry, AlignLeft, MARGIN, globalconf.prompt, globalconf.styles.focus); - len = MARGIN * 2 + draw_textwidth(globalconf.connection, globalconf.default_screen, - globalconf.styles.focus.font, globalconf.prompt); + len = MARGIN * 2 + draw_text_extents(globalconf.connection, globalconf.default_screen, + globalconf.styles.focus.font, globalconf.prompt).width; geometry.x += len; geometry.width -= len; } @@ -443,8 +443,8 @@ redraw(void) draw_text(globalconf.ctx, geometry, AlignLeft, MARGIN, globalconf.text, globalconf.styles.normal); - len = MARGIN * 2 + MAX(draw_textwidth(globalconf.connection, globalconf.default_screen, - globalconf.styles.normal.font, globalconf.text), + len = MARGIN * 2 + MAX(draw_text_extents(globalconf.connection, globalconf.default_screen, + globalconf.styles.normal.font, globalconf.text).width, geometry.width / 20); geometry.x += len; geometry.width -= len; @@ -454,8 +454,8 @@ redraw(void) if(item->match) { style = item == globalconf.item_selected ? globalconf.styles.focus : globalconf.styles.normal; - len = MARGIN + draw_textwidth(globalconf.connection, globalconf.default_screen, - style.font, item->data); + len = MARGIN + draw_text_extents(globalconf.connection, globalconf.default_screen, + style.font, item->data).width; if(item == globalconf.item_selected) { if(len > geometry.width) @@ -479,8 +479,8 @@ redraw(void) { style = item == globalconf.item_selected ? globalconf.styles.focus : globalconf.styles.normal; x_of_previous_item = geometry.x; - geometry.width = MARGIN + draw_textwidth(globalconf.connection, globalconf.default_screen, - style.font, item->data); + geometry.width = MARGIN + draw_text_extents(globalconf.connection, globalconf.default_screen, + style.font, item->data).width; geometry.x -= geometry.width; if(geometry.x < prompt_len) diff --git a/awesome-message.c b/awesome-message.c index 1225f5270..290d2734a 100644 --- a/awesome-message.c +++ b/awesome-message.c @@ -187,8 +187,8 @@ main(int argc, char **argv) if((ret = config_parse(screen, configfile))) return ret; - geometry.width = draw_textwidth(globalconf.connection, globalconf.default_screen, - globalconf.style.font, argv[optind]); + geometry.width = draw_text_extents(globalconf.connection, globalconf.default_screen, + globalconf.style.font, argv[optind]).width; geometry.height = globalconf.style.font->height * 1.5; if(argc - optind >= 2) diff --git a/common/configopts.c b/common/configopts.c index 6ef660591..25acfe8f7 100644 --- a/common/configopts.c +++ b/common/configopts.c @@ -196,8 +196,12 @@ cfg_opt_t titlebar_opts[] = CFG_INT((char *) "height", 0, CFGF_NONE), /** Text alignment. */ CFG_ALIGNMENT((char *) "text_align", (char *) "center", CFGF_NONE), - /** Titlebar styles. */ - CFG_SEC((char *) "styles", styles_opts, CFGF_NONE), + /** Titlebar markup string for focused windows. */ + CFG_STR((char *) "text_focus", (char *) "%t", CFGF_NONE), + /** Titlebar markup string for normal windows. */ + CFG_STR((char *) "text_normal", (char *) "%t", CFGF_NONE), + /** Titlebar markup string for urgent windows. */ + CFG_STR((char *) "text_urgent", (char *) "%t", CFGF_NONE), CFG_AWESOME_END() }; /** This section defines general options. */ diff --git a/common/draw.c b/common/draw.c index 44b01c264..5c06cd720 100644 --- a/common/draw.c +++ b/common/draw.c @@ -221,6 +221,7 @@ draw_font_delete(font_t **font) * \param enable shadow * \param fg foreground color * \param bg background color + * \return area_t with width and height are set to what used */ void draw_text(DrawCtx *ctx, @@ -249,7 +250,7 @@ draw_text(DrawCtx *ctx, buf = a_strdup(text); /* check that the text is not too long */ - while(len && (nw = (draw_textwidth(ctx->connection, ctx->default_screen, style.font, buf)) + padding * 2) > area.width) + while(len && (nw = (draw_text_extents(ctx->connection, ctx->default_screen, style.font, buf).width) + padding * 2) > area.width) { len--; /* we can't blindly null the char, we need to check if it's not part of @@ -866,18 +867,19 @@ draw_rotate(DrawCtx *ctx, xcb_drawable_t dest, int dest_w, int dest_h, * \param text the text * \return text width */ -unsigned short -draw_textwidth(xcb_connection_t *conn, int default_screen, font_t *font, const char *text) +area_t +draw_text_extents(xcb_connection_t *conn, int default_screen, font_t *font, const char *text) { cairo_surface_t *surface; cairo_t *cr; PangoLayout *layout; PangoRectangle ext; xcb_screen_t *s = xcb_aux_get_screen(conn, default_screen); + area_t geom = { 0, 0, 0, 0, NULL, NULL }; ssize_t len; if(!(len = a_strlen(text))) - return 0; + return geom; surface = cairo_xcb_surface_create(conn, default_screen, draw_screen_default_visual(s), @@ -892,7 +894,10 @@ draw_textwidth(xcb_connection_t *conn, int default_screen, font_t *font, const c cairo_destroy(cr); cairo_surface_destroy(surface); - return ext.width; + geom.width = ext.width; + geom.height = ext.height * 1.5; + + return geom; } /** Transform a string to a alignment_t type. diff --git a/common/draw.h b/common/draw.h index 34acb93ff..eb07eeb27 100644 --- a/common/draw.h +++ b/common/draw.h @@ -137,7 +137,7 @@ void draw_image(DrawCtx *, int, int, int, const char *); void draw_image_from_argb_data(DrawCtx *, int, int, int, int, int, unsigned char *); area_t draw_get_image_size(const char *filename); void draw_rotate(DrawCtx *, xcb_drawable_t, int, int, double, int, int); -unsigned short draw_textwidth(xcb_connection_t *, int, font_t *, const char *); +area_t draw_text_extents(xcb_connection_t *, int, font_t *, const char *); alignment_t draw_align_get_from_str(const char *); bool draw_color_new(xcb_connection_t *, int, const char *, xcolor_t *); void draw_style_init(xcb_connection_t *, int, cfg_t *, style_t *, style_t *); diff --git a/config.c b/config.c index d3684fcf9..908fa87f4 100644 --- a/config.c +++ b/config.c @@ -281,28 +281,16 @@ statusbar_widgets_create(cfg_t *cfg_statusbar, statusbar_t *statusbar) } static void -config_section_titlebar_init(cfg_t *cfg_titlebar, titlebar_t *tb, int screen) +config_section_titlebar_init(cfg_t *cfg_titlebar, titlebar_t *tb) { - int phys_screen = screen_virttophys(screen); - cfg_t *cfg_styles = cfg_getsec(cfg_titlebar, "styles"); - tb->position = tb->dposition = cfg_getposition(cfg_titlebar, "position"); tb->align = cfg_getalignment(cfg_titlebar, "align"); tb->text_align = cfg_getalignment(cfg_titlebar, "text_align"); tb->width = cfg_getint(cfg_titlebar, "width"); tb->height = cfg_getint(cfg_titlebar, "height"); - draw_style_init(globalconf.connection, phys_screen, - cfg_getsec(cfg_styles, "normal"), - &tb->styles.normal, - &globalconf.screens[screen].styles.normal); - draw_style_init(globalconf.connection, phys_screen, - cfg_getsec(cfg_styles, "focus"), - &tb->styles.focus, - &globalconf.screens[screen].styles.focus); - draw_style_init(globalconf.connection, phys_screen, - cfg_getsec(cfg_styles, "urgent"), - &tb->styles.urgent, - &globalconf.screens[screen].styles.urgent); + tb->text_normal = a_strdup(cfg_getstr(cfg_titlebar, "text_normal")); + tb->text_focus = a_strdup(cfg_getstr(cfg_titlebar, "text_focus")); + tb->text_urgent = a_strdup(cfg_getstr(cfg_titlebar, "text_urgent")); } static void @@ -392,7 +380,7 @@ config_parse_screen(cfg_t *cfg, int screen) eprint("no font available\n"); /* Titlebar */ - config_section_titlebar_init(cfg_titlebar, &virtscreen->titlebar_default, screen); + config_section_titlebar_init(cfg_titlebar, &virtscreen->titlebar_default); /* statusbar_t */ statusbar_list_init(&virtscreen->statusbar); @@ -544,7 +532,7 @@ config_parse(const char *confpatharg) rule->screen = cfg_getint(cfgsectmp, "screen"); rule->ismaster = fuzzy_get_from_str(cfg_getstr(cfgsectmp, "master")); rule->opacity = cfg_getfloat(cfgsectmp, "opacity"); - config_section_titlebar_init(cfg_getsec(cfgsectmp, "titlebar"), &rule->titlebar, 0); + config_section_titlebar_init(cfg_getsec(cfgsectmp, "titlebar"), &rule->titlebar); if(rule->screen >= globalconf.screens_info->nscreen) rule->screen = 0; diff --git a/mouse.c b/mouse.c index c3dfc88a8..b87fabb23 100644 --- a/mouse.c +++ b/mouse.c @@ -165,11 +165,10 @@ mouse_resizebar_new(int phys_screen, int border, area_t geometry, style_t style, simple_window_t *sw; area_t geom; - geom.width = draw_textwidth(globalconf.connection, - globalconf.default_screen, - style.font, - "0000x0000+0000+0000") + style.font->height; - geom.height = 1.5 * style.font->height; + geom = draw_text_extents(globalconf.connection, + globalconf.default_screen, + style.font, + "0000x0000+0000+0000"); geom.x = geometry.x + ((2 * border + geometry.width) - geom.width) / 2; geom.y = geometry.y + ((2 * border + geometry.height) - geom.height) / 2; diff --git a/structs.h b/structs.h index 983c70eb5..91e384493 100644 --- a/structs.h +++ b/structs.h @@ -53,13 +53,7 @@ typedef struct alignment_t align; alignment_t text_align; int width, height; - /** Colors */ - struct - { - style_t normal; - style_t focus; - style_t urgent; - } styles; + char *text_normal, *text_focus, *text_urgent; } titlebar_t; /** Rule type */ diff --git a/titlebar.c b/titlebar.c index 84c14797c..3dd49947e 100644 --- a/titlebar.c +++ b/titlebar.c @@ -30,6 +30,61 @@ extern AwesomeConf globalconf; +static char * +titlebar_markup_parse(client_t *c, const char *str, ssize_t len) +{ + const char *ps; + char *new; + int i = 0; + ssize_t clen; + + new = p_new(char, len++); + + for(ps = str; *ps; ps++, i++) + { + if(*ps == '%') + { + ps++; + if(*ps == '%') + new[i] = '%'; + else if(*ps == 't') + { + clen = a_strlen(c->name); + len += clen; + p_realloc(&new, len); + a_strcat(new + i, len - i, c->name); + i += clen - 1; + } + } + else + new[i] = *ps; + } + + return new; +} + +static char * +titlebar_text(client_t *c) +{ + char *text; + + if(globalconf.focus->client == c) + text = c->titlebar.text_focus; + else if(c->isurgent) + text = c->titlebar.text_urgent; + else + text = c->titlebar.text_normal; + + return titlebar_markup_parse(c, text, a_strlen(text)); +} + +static inline area_t +titlebar_size(client_t *c) +{ + return draw_text_extents(globalconf.connection, globalconf.default_screen, + globalconf.screens[c->screen].styles.normal.font, titlebar_text(c)); +} + /** Initialize a titlebar: create the simple_window_t. * We still need to update its geometry to have it placed correctly. * \param c the client @@ -37,18 +92,21 @@ extern AwesomeConf globalconf; void titlebar_init(client_t *c) { - int width; + int width = 0, height = 0; if(!c->titlebar.height) - c->titlebar.height = 1.5 * MAX(c->titlebar.styles.normal.font->height, - MAX(c->titlebar.styles.focus.font->height, - c->titlebar.styles.urgent.font->height)); + c->titlebar.height = MAX(MAX(draw_text_extents(globalconf.connection, globalconf.default_screen, + globalconf.screens[c->screen].styles.normal.font, c->titlebar.text_focus).height, + draw_text_extents(globalconf.connection, globalconf.default_screen, + globalconf.screens[c->screen].styles.normal.font, c->titlebar.text_normal).height), + draw_text_extents(globalconf.connection, globalconf.default_screen, + globalconf.screens[c->screen].styles.normal.font, c->titlebar.text_urgent).height); switch(c->titlebar.position) { case Off: return; - case Auto: + default: c->titlebar.position = Off; return; case Top: @@ -57,23 +115,20 @@ titlebar_init(client_t *c) width = c->geometry.width + 2 * c->border; else width = MIN(c->titlebar.width, c->geometry.width); - c->titlebar.sw = simplewindow_new(globalconf.connection, - c->phys_screen, 0, 0, - width, c->titlebar.height, 0); + height = c->titlebar.height; break; case Left: case Right: if(!c->titlebar.width) - width = c->geometry.height + 2 * c->border; + height = c->geometry.height + 2 * c->border; else - width = MIN(c->titlebar.width, c->geometry.height); - c->titlebar.sw = simplewindow_new(globalconf.connection, - c->phys_screen, 0, 0, - c->titlebar.height, width, 0); - break; - default: + height = MIN(c->titlebar.width, c->geometry.height); + width = c->titlebar.height; break; } + c->titlebar.sw = simplewindow_new(globalconf.connection, + c->phys_screen, 0, 0, + width, height, 0); xcb_map_window(globalconf.connection, c->titlebar.sw->window); } @@ -153,9 +208,9 @@ titlebar_draw(client_t *c) { xcb_drawable_t dw = 0; DrawCtx *ctx; - style_t style; area_t geometry; xcb_screen_t *s; + char *text; if(!c->titlebar.sw) return; @@ -191,18 +246,11 @@ titlebar_draw(client_t *c) break; } - /* Check if the client is focused/urgent/normal */ - if(globalconf.focus->client == c) - style = c->titlebar.styles.focus; - else if(c->isurgent) - style = c->titlebar.styles.urgent; - else - style = c->titlebar.styles.normal; - + text = titlebar_text(c); geometry.x = geometry.y = 0; - - draw_text(ctx, geometry, c->titlebar.text_align, style.font->height / 2, - c->name, style); + draw_text(ctx, geometry, c->titlebar.text_align, 0, + text, globalconf.screens[c->screen].styles.normal); + p_delete(&text); switch(c->titlebar.position) { diff --git a/widgets/taglist.c b/widgets/taglist.c index cfc4bd0d5..f83e206ef 100644 --- a/widgets/taglist.c +++ b/widgets/taglist.c @@ -90,9 +90,8 @@ taglist_draw(widget_t *widget, for(tag = vscreen.tags; tag; tag = tag->next) { style = tag->selected ? vscreen.styles.focus : vscreen.styles.normal; - widget->area.width += draw_textwidth(ctx->connection, ctx->default_screen, - style.font, tag->name) - + style.font->height; + widget->area.width += draw_text_extents(ctx->connection, ctx->default_screen, + style.font, tag->name).width + style.font->height; } if(!widget->user_supplied_x) @@ -108,8 +107,8 @@ taglist_draw(widget_t *widget, for(tag = vscreen.tags; tag; tag = tag->next) { style = taglist_style_get(vscreen, tag); - w = draw_textwidth(ctx->connection, ctx->default_screen, - style.font, tag->name) + style.font->height; + w = draw_text_extents(ctx->connection, ctx->default_screen, + style.font, tag->name).width + style.font->height; area.x = widget->area.x + widget->area.width; area.y = widget->area.y; area.width = w; @@ -155,8 +154,8 @@ taglist_button_press(widget_t *widget, xcb_button_press_event_t *ev) for(tag = vscreen.tags; tag; tag = tag->next, i++) { style = taglist_style_get(vscreen, tag); - width = draw_textwidth(globalconf.connection, globalconf.default_screen, - style.font, tag->name) + width = draw_text_extents(globalconf.connection, globalconf.default_screen, + style.font, tag->name).width + style.font->height; if(ev->event_x >= widget->area.x + prev_width && ev->event_x < widget->area.x + prev_width + width) @@ -172,8 +171,8 @@ taglist_button_press(widget_t *widget, xcb_button_press_event_t *ev) for(tag = vscreen.tags; tag; tag = tag->next, i++) { style = taglist_style_get(vscreen, tag); - width = draw_textwidth(globalconf.connection, globalconf.default_screen, - style.font, tag->name) + style.font->height; + width = draw_text_extents(globalconf.connection, globalconf.default_screen, + style.font, tag->name).width + style.font->height; if(ev->event_y >= widget->area.x + prev_width && ev->event_y < widget->area.x + prev_width + width) { @@ -188,8 +187,8 @@ taglist_button_press(widget_t *widget, xcb_button_press_event_t *ev) for(tag = vscreen.tags; tag; tag = tag->next, i++) { style = taglist_style_get(vscreen, tag); - width = draw_textwidth(globalconf.connection, globalconf.default_screen, - style.font, tag->name) + style.font->height; + width = draw_text_extents(globalconf.connection, globalconf.default_screen, + style.font, tag->name).width + style.font->height; if(widget->statusbar->width - ev->event_y >= widget->area.x + prev_width && widget->statusbar->width - ev->event_y < widget->area.x + prev_width + width) { diff --git a/widgets/textbox.c b/widgets/textbox.c index d7486343b..4ada84cda 100644 --- a/widgets/textbox.c +++ b/widgets/textbox.c @@ -44,8 +44,8 @@ textbox_draw(widget_t *widget, DrawCtx *ctx, int offset, int used) else if(widget->alignment == AlignFlex) widget->area.width = widget->statusbar->width - used; else - widget->area.width = MIN(draw_textwidth(ctx->connection, ctx->default_screen, - d->style.font, d->text), + widget->area.width = MIN(draw_text_extents(ctx->connection, ctx->default_screen, + d->style.font, d->text).width, widget->statusbar->width - used); widget->area.height = widget->statusbar->height;