[draw] Add support for bg in draw_text and use ellipsize from pango
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
16d98db666
commit
1185d8b156
|
@ -196,12 +196,12 @@ cfg_opt_t titlebar_opts[] =
|
||||||
CFG_INT((char *) "height", 0, CFGF_NONE),
|
CFG_INT((char *) "height", 0, CFGF_NONE),
|
||||||
/** Text alignment. */
|
/** Text alignment. */
|
||||||
CFG_ALIGNMENT((char *) "text_align", (char *) "center", CFGF_NONE),
|
CFG_ALIGNMENT((char *) "text_align", (char *) "center", CFGF_NONE),
|
||||||
/** Titlebar markup string for focused windows. */
|
|
||||||
CFG_STR((char *) "text_focus", (char *) "%t", CFGF_NONE),
|
|
||||||
/** Titlebar markup string for normal windows. */
|
/** Titlebar markup string for normal windows. */
|
||||||
CFG_STR((char *) "text_normal", (char *) "%t", CFGF_NONE),
|
CFG_STR((char *) "text_normal", (char *) "<bg color=\"#444444\"/>%t", CFGF_NONE),
|
||||||
|
/** Titlebar markup string for focused windows. */
|
||||||
|
CFG_STR((char *) "text_focus", (char *) "<bg color=\"#535d6c\"/>%t", CFGF_NONE),
|
||||||
/** Titlebar markup string for urgent windows. */
|
/** Titlebar markup string for urgent windows. */
|
||||||
CFG_STR((char *) "text_urgent", (char *) "%t", CFGF_NONE),
|
CFG_STR((char *) "text_urgent", (char *) "<bg color=\"#ff4500\"/>%t", CFGF_NONE),
|
||||||
CFG_AWESOME_END()
|
CFG_AWESOME_END()
|
||||||
};
|
};
|
||||||
/** This section defines general options. */
|
/** This section defines general options. */
|
||||||
|
|
134
common/draw.c
134
common/draw.c
|
@ -35,7 +35,7 @@
|
||||||
#include <iconv.h>
|
#include <iconv.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
* \return NULL if error, otherwise pointer to the new converted string
|
* \return NULL if error, otherwise pointer to the new converted string
|
||||||
*/
|
*/
|
||||||
static char *
|
static char *
|
||||||
draw_iso2utf8(char *iso)
|
draw_iso2utf8(const char *iso)
|
||||||
{
|
{
|
||||||
iconv_t iso2utf8;
|
iconv_t iso2utf8;
|
||||||
size_t len, utf8len;
|
size_t len, utf8len;
|
||||||
|
@ -74,7 +74,7 @@ draw_iso2utf8(char *iso)
|
||||||
utf8len = 2 * len + 1;
|
utf8len = 2 * len + 1;
|
||||||
utf8 = utf8p = p_new(char, utf8len);
|
utf8 = utf8p = p_new(char, utf8len);
|
||||||
|
|
||||||
if(iconv(iso2utf8, &iso, &len, &utf8, &utf8len) == (size_t) -1)
|
if(iconv(iso2utf8, (char **) &iso, &len, &utf8, &utf8len) == (size_t) -1)
|
||||||
{
|
{
|
||||||
warn("text conversion failed: %s\n", strerror(errno));
|
warn("text conversion failed: %s\n", strerror(errno));
|
||||||
p_delete(&utf8p);
|
p_delete(&utf8p);
|
||||||
|
@ -211,6 +211,60 @@ draw_font_delete(font_t **font)
|
||||||
p_delete(font);
|
p_delete(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
draw_text_markup_expand(xcb_connection_t *conn,
|
||||||
|
int phys_screen,
|
||||||
|
const char *str, ssize_t slen,
|
||||||
|
xcolor_t **bg_color)
|
||||||
|
{
|
||||||
|
const char *ps;
|
||||||
|
char *bg, *bg_end, *bg_str, *color, *col_end, *col_str, *new;
|
||||||
|
ssize_t len;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if((bg = strstr(str, "<bg "))
|
||||||
|
&& ((bg_end = strstr(bg, "/>"))))
|
||||||
|
{
|
||||||
|
len = bg_end - bg + 1;
|
||||||
|
bg_str = p_new(char, len);
|
||||||
|
/* strncpy(bg_str, len, bg + len of '<bg ', everything * exclude >) */
|
||||||
|
a_strncpy(bg_str, len, bg + 4, len - 5);
|
||||||
|
|
||||||
|
if(bg_color && (color = strstr(bg_str, "color=")))
|
||||||
|
{
|
||||||
|
color += 6;
|
||||||
|
if(color[0] == '"')
|
||||||
|
color++;
|
||||||
|
for(col_end = color; *col_end && (*col_end == '#' || isalnum(*col_end)); col_end++);
|
||||||
|
|
||||||
|
col_str = a_strndup(color, col_end - color);
|
||||||
|
|
||||||
|
if((len = a_strlen(col_str)))
|
||||||
|
{
|
||||||
|
if(col_str[len - 1] == '"')
|
||||||
|
col_str[--len] = '\0';
|
||||||
|
*bg_color = p_new(xcolor_t, 1);
|
||||||
|
if(!draw_color_new(conn, phys_screen, col_str, *bg_color))
|
||||||
|
p_delete(bg_color);
|
||||||
|
}
|
||||||
|
p_delete(&col_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy string without <bg> */
|
||||||
|
new = p_new(char, slen - (bg_end - bg));
|
||||||
|
for(ps = str; *ps; ps++)
|
||||||
|
/* if before <bg and after /> */
|
||||||
|
if(ps < bg || ps > (bg_end + 1))
|
||||||
|
new[i++] = *ps;
|
||||||
|
|
||||||
|
p_delete(&bg_str);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
new = a_strdup(str);
|
||||||
|
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
/** Draw text into a draw context
|
/** Draw text into a draw context
|
||||||
* \param ctx DrawCtx to draw to
|
* \param ctx DrawCtx to draw to
|
||||||
* \param area area to draw to
|
* \param area area to draw to
|
||||||
|
@ -228,53 +282,41 @@ draw_text(DrawCtx *ctx,
|
||||||
area_t area,
|
area_t area,
|
||||||
alignment_t align,
|
alignment_t align,
|
||||||
int padding,
|
int padding,
|
||||||
char *text,
|
const char *text,
|
||||||
style_t style)
|
style_t style)
|
||||||
{
|
{
|
||||||
int nw = 0, x, y;
|
int x, y;
|
||||||
ssize_t len, olen;
|
ssize_t len, olen;
|
||||||
char *buf = NULL, *utf8 = NULL;
|
char *buf = NULL, *utf8 = NULL;
|
||||||
|
xcolor_t *bg_color = NULL;
|
||||||
|
PangoRectangle ext;
|
||||||
|
|
||||||
draw_rectangle(ctx, area, 1.0, true, style.bg);
|
if(!(len = a_strlen(text)))
|
||||||
|
|
||||||
if(!(len = olen = a_strlen(text)))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* try to convert it to UTF-8 */
|
/* try to convert it to UTF-8 */
|
||||||
if((utf8 = draw_iso2utf8(text)))
|
if((utf8 = draw_iso2utf8(text)))
|
||||||
{
|
len = a_strlen(utf8);
|
||||||
buf = utf8;
|
|
||||||
len = olen = a_strlen(buf);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
buf = a_strdup(text);
|
utf8 = a_strdup(text);
|
||||||
|
|
||||||
/* check that the text is not too long */
|
buf = draw_text_markup_expand(ctx->connection, ctx->phys_screen,
|
||||||
while(len && (nw = (draw_text_extents(ctx->connection, ctx->default_screen, style.font, buf).width) + padding * 2) > area.width)
|
utf8, len, &bg_color);
|
||||||
|
p_delete(&utf8);
|
||||||
|
|
||||||
|
len = olen = a_strlen(buf);
|
||||||
|
|
||||||
|
if(bg_color)
|
||||||
{
|
{
|
||||||
len--;
|
draw_rectangle(ctx, area, 1.0, true, *bg_color);
|
||||||
/* we can't blindly null the char, we need to check if it's not part of
|
p_delete(&bg_color);
|
||||||
* a multi byte char: if mbtowc return -1, we know that we must go back
|
|
||||||
* in the string to find the beginning of the multi byte char */
|
|
||||||
while(len && mbtowc(NULL, buf + len, a_strlen(buf + len)) < 0)
|
|
||||||
len--;
|
|
||||||
buf[len] = '\0';
|
|
||||||
}
|
|
||||||
/* check that text is not too long */
|
|
||||||
if(nw > area.width)
|
|
||||||
return;
|
|
||||||
if(len < olen)
|
|
||||||
{
|
|
||||||
if(len > 1)
|
|
||||||
buf[len - 1] = '.';
|
|
||||||
if(len > 2)
|
|
||||||
buf[len - 2] = '.';
|
|
||||||
if(len > 3)
|
|
||||||
buf[len - 3] = '.';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pango_layout_set_width(ctx->layout, pango_units_from_double(area.width));
|
||||||
|
pango_layout_set_ellipsize(ctx->layout, PANGO_ELLIPSIZE_END);
|
||||||
pango_layout_set_markup(ctx->layout, buf, len);
|
pango_layout_set_markup(ctx->layout, buf, len);
|
||||||
pango_layout_set_font_description(ctx->layout, style.font->desc);
|
pango_layout_set_font_description(ctx->layout, style.font->desc);
|
||||||
|
pango_layout_get_pixel_extents(ctx->layout, NULL, &ext);
|
||||||
|
|
||||||
x = area.x + padding;
|
x = area.x + padding;
|
||||||
/* + 1 is added for rounding, so that in any case of doubt we rather draw
|
/* + 1 is added for rounding, so that in any case of doubt we rather draw
|
||||||
|
@ -285,15 +327,17 @@ draw_text(DrawCtx *ctx,
|
||||||
switch(align)
|
switch(align)
|
||||||
{
|
{
|
||||||
case AlignCenter:
|
case AlignCenter:
|
||||||
x += (area.width - nw) / 2;
|
x += (area.width - ext.width) / 2;
|
||||||
break;
|
break;
|
||||||
case AlignRight:
|
case AlignRight:
|
||||||
x += area.width - nw;
|
x += area.width - ext.width;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cairo_move_to(ctx->cr, x, y);
|
||||||
|
|
||||||
if(style.shadow_offset > 0)
|
if(style.shadow_offset > 0)
|
||||||
{
|
{
|
||||||
cairo_set_source_rgb(ctx->cr,
|
cairo_set_source_rgb(ctx->cr,
|
||||||
|
@ -309,7 +353,6 @@ draw_text(DrawCtx *ctx,
|
||||||
style.fg.red / 65535.0,
|
style.fg.red / 65535.0,
|
||||||
style.fg.green / 65535.0,
|
style.fg.green / 65535.0,
|
||||||
style.fg.blue / 65535.0);
|
style.fg.blue / 65535.0);
|
||||||
cairo_move_to(ctx->cr, x, y);
|
|
||||||
pango_cairo_update_layout(ctx->cr, ctx->layout);
|
pango_cairo_update_layout(ctx->cr, ctx->layout);
|
||||||
pango_cairo_show_layout(ctx->cr, ctx->layout);
|
pango_cairo_show_layout(ctx->cr, ctx->layout);
|
||||||
|
|
||||||
|
@ -877,17 +920,30 @@ draw_text_extents(xcb_connection_t *conn, int default_screen, font_t *font, cons
|
||||||
xcb_screen_t *s = xcb_aux_get_screen(conn, default_screen);
|
xcb_screen_t *s = xcb_aux_get_screen(conn, default_screen);
|
||||||
area_t geom = { 0, 0, 0, 0, NULL, NULL };
|
area_t geom = { 0, 0, 0, 0, NULL, NULL };
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
char *buf, *utf8;
|
||||||
|
|
||||||
if(!(len = a_strlen(text)))
|
if(!(len = a_strlen(text)))
|
||||||
return geom;
|
return geom;
|
||||||
|
|
||||||
|
/* try to convert it to UTF-8 */
|
||||||
|
if((utf8 = draw_iso2utf8(text)))
|
||||||
|
len = a_strlen(utf8);
|
||||||
|
else
|
||||||
|
utf8 = a_strdup(text);
|
||||||
|
|
||||||
|
buf = draw_text_markup_expand(conn, default_screen, utf8, len, NULL);
|
||||||
|
p_delete(&utf8);
|
||||||
|
|
||||||
|
len = a_strlen(buf);
|
||||||
|
|
||||||
surface = cairo_xcb_surface_create(conn, default_screen,
|
surface = cairo_xcb_surface_create(conn, default_screen,
|
||||||
draw_screen_default_visual(s),
|
draw_screen_default_visual(s),
|
||||||
s->width_in_pixels,
|
s->width_in_pixels,
|
||||||
s->height_in_pixels);
|
s->height_in_pixels);
|
||||||
|
|
||||||
cr = cairo_create(surface);
|
cr = cairo_create(surface);
|
||||||
layout = pango_cairo_create_layout(cr);
|
layout = pango_cairo_create_layout(cr);
|
||||||
pango_layout_set_markup(layout, text, len);
|
pango_layout_set_markup(layout, buf, len);
|
||||||
pango_layout_set_font_description(layout, font->desc);
|
pango_layout_set_font_description(layout, font->desc);
|
||||||
pango_layout_get_pixel_extents(layout, NULL, &ext);
|
pango_layout_get_pixel_extents(layout, NULL, &ext);
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
@ -897,6 +953,8 @@ draw_text_extents(xcb_connection_t *conn, int default_screen, font_t *font, cons
|
||||||
geom.width = ext.width;
|
geom.width = ext.width;
|
||||||
geom.height = ext.height * 1.5;
|
geom.height = ext.height * 1.5;
|
||||||
|
|
||||||
|
p_delete(&buf);
|
||||||
|
|
||||||
return geom;
|
return geom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ void draw_context_delete(DrawCtx **);
|
||||||
font_t *draw_font_new(xcb_connection_t *, int, char *);
|
font_t *draw_font_new(xcb_connection_t *, int, char *);
|
||||||
void draw_font_delete(font_t **);
|
void draw_font_delete(font_t **);
|
||||||
|
|
||||||
void draw_text(DrawCtx *, area_t, alignment_t, int, char *, style_t);
|
void draw_text(DrawCtx *, area_t, alignment_t, int, const char *, style_t);
|
||||||
void draw_rectangle(DrawCtx *, area_t, float, bool, xcolor_t);
|
void draw_rectangle(DrawCtx *, area_t, float, bool, xcolor_t);
|
||||||
void draw_rectangle_gradient(DrawCtx *, area_t, float, bool, area_t, xcolor_t *, xcolor_t *, xcolor_t *);
|
void draw_rectangle_gradient(DrawCtx *, area_t, float, bool, area_t, xcolor_t *, xcolor_t *, xcolor_t *);
|
||||||
|
|
||||||
|
|
|
@ -113,11 +113,7 @@ taglist_draw(widget_t *widget,
|
||||||
area.y = widget->area.y;
|
area.y = widget->area.y;
|
||||||
area.width = w;
|
area.width = w;
|
||||||
area.height = widget->statusbar->height;
|
area.height = widget->statusbar->height;
|
||||||
draw_text(ctx, area,
|
draw_text(ctx, area, AlignCenter, 0, tag->name, style);
|
||||||
AlignCenter,
|
|
||||||
style.font->height / 2,
|
|
||||||
tag->name,
|
|
||||||
style);
|
|
||||||
|
|
||||||
if(isoccupied(tag))
|
if(isoccupied(tag))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue