From 54c25e659002c909356cb4f9b5f847f891f84faa Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Thu, 23 Jan 2014 23:00:33 +0100 Subject: [PATCH] New display code supports sliders and percentages They come in two possible designs, selectable by compile-time switch SLIDERS_WITH_BRACKETS in display.c. I yet have to decide which design should be the default one and if it should be possible to switch designs in run-time. --- display.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++----- display.h | 6 +++- osdd.c | 12 +++---- 3 files changed, 101 insertions(+), 15 deletions(-) diff --git a/display.c b/display.c index 8bb7999..8f82dca 100644 --- a/display.c +++ b/display.c @@ -1,7 +1,7 @@ /* * On-screen Display * - * (c) 2013 Martin Mares + * (c) 2013--2014 Martin Mares * * This code is heavily inspired by the libxosd library, * which is (c) 2000, 2001 Andre Renaud . @@ -22,6 +22,8 @@ #include "util.h" #include "display.h" +#define SLIDERS_WITH_BRACKETS + struct osd_state { // Basic characteristics of current display and screen Display *dpy; @@ -55,6 +57,10 @@ struct osd_state { int line_height; int line_skip; bool visible; + + // Used temporarily when drawing a line + XftColor fg_color; + XftColor mask_color; }; static void @@ -183,6 +189,10 @@ struct osd_line *osd_add_line(struct osd_state *osd, enum osd_line_type type) case OSD_TYPE_TEXT: l->u.text[0] = 0; break; + case OSD_TYPE_PERCENTAGE: + case OSD_TYPE_SLIDER: + l->u.percent = 0; + break; default: die("osd_add_line: unknown type %d", type); } @@ -204,6 +214,27 @@ static void osd_prepare_line(struct osd_state *osd, int i) line->height = osd->line_distance + 2*line->outline_width; break; } + case OSD_TYPE_PERCENTAGE: + case OSD_TYPE_SLIDER: + { +#ifdef SLIDERS_WITH_BRACKETS + line->slider_unit = osd->line_height / 5; + line->slider_space = osd->line_height / 5; +#else + line->slider_unit = osd->line_height / 3; + line->slider_space = osd->line_height / 6; +#endif + if (!line->slider_space) + line->slider_space = line->slider_unit = 1; + int use_width = osd->screen_width * 4 / 5; + int u = line->slider_unit + line->slider_space; + line->slider_units = (use_width + line->slider_space) / u; + if (line->slider_units < 3) + line->slider_units = 3; + line->width = line->slider_units*u - line->slider_space + 2*line->outline_width; + line->height = osd->line_height + 2*line->outline_width; + break; + } default: die("osd_recalc_line: unknown type %d", line->type); } @@ -252,16 +283,24 @@ static void osd_prepare(struct osd_state *osd) } } +static void osd_draw_box(struct osd_state *osd, struct osd_line *line, int x, int y, int w, int h) +{ + XftDrawRect(osd->mask_draw, &osd->mask_color, + x - line->outline_width, y - line->outline_width, + w + 2*line->outline_width, h + 2*line->outline_width); + XftDrawRect(osd->image_draw, &osd->fg_color, x, y, w, h); +} + static void osd_draw_line(struct osd_state *osd, int i) { struct osd_line *line = &osd->lines[i]; // Allocate colors - XftColor fg_color, outline_color, mask_color; + XftColor outline_color; XRenderColor mask_rc = { .red = 0xffff, .green = 0xffff, .blue = 0xffff, .alpha = 0xffff }; - if (!XftColorAllocName(osd->dpy, osd->visual, osd->cmap, line->fg_color, &fg_color) || + if (!XftColorAllocName(osd->dpy, osd->visual, osd->cmap, line->fg_color, &osd->fg_color) || !XftColorAllocName(osd->dpy, osd->visual, osd->cmap, line->outline_color, &outline_color) || - !XftColorAllocValue(osd->dpy, osd->visual, osd->cmap, &mask_rc, &mask_color)) + !XftColorAllocValue(osd->dpy, osd->visual, osd->cmap, &mask_rc, &osd->mask_color)) die("Cannot allocate colors"); // Draw background in outline color @@ -276,24 +315,67 @@ static void osd_draw_line(struct osd_state *osd, int i) unsigned char *text = (unsigned char *) line->u.text; int text_len = strlen(line->u.text); - XftDrawStringUtf8(osd->image_draw, &fg_color, osd->font, x, y, text, text_len); + XftDrawStringUtf8(osd->image_draw, &osd->fg_color, osd->font, x, y, text, text_len); // This is slow, but unlike the method used by libxosd, the result isn't ugly. int outline = line->outline_width; for (int dx = -outline; dx <= outline; dx++) for (int dy = -outline; dy <= outline; dy++) if (dx*dx + dy*dy <= outline*outline) - XftDrawStringUtf8(osd->mask_draw, &mask_color, osd->font, x + dx, y + dy, text, text_len); + XftDrawStringUtf8(osd->mask_draw, &osd->mask_color, osd->font, x + dx, y + dy, text, text_len); + break; + } + case OSD_TYPE_PERCENTAGE: + case OSD_TYPE_SLIDER: + { + int x = line->x_pos + line->outline_width; + int y = line->y_pos + line->outline_width; + int su = line->slider_unit; + int advance = su + line->slider_space; + int units = line->slider_units; +#ifdef SLIDERS_WITH_BRACKETS + units -= 2; + int hu = osd->line_height / 5; + int hd = 2*hu; + osd_draw_box(osd, line, x, y, su - su/3, 5*hu); + osd_draw_box(osd, line, x, y, su, hu); + osd_draw_box(osd, line, x, y + 4*hu, su, hu); + x += advance; +#else + int hu = osd->line_height / 3; + int hd = hu; +#endif + int min, max; + if (line->type == OSD_TYPE_PERCENTAGE) + { + min = 0; + max = (units+1) * line->u.percent / 100 - 1; + } + else + min = max = (units-1) * line->u.percent / 100; + for (int i=0; i < units; i++) + { + if (i >= min && i <= max) + osd_draw_box(osd, line, x, y, su, osd->line_height); + else + osd_draw_box(osd, line, x, y + hd, su, hu); + x += advance; + } +#ifdef SLIDERS_WITH_BRACKETS + osd_draw_box(osd, line, x + su/3, y, su - su/3, 5*hu); + osd_draw_box(osd, line, x, y, su, hu); + osd_draw_box(osd, line, x, y + 4*hu, su, hu); +#endif break; } default: die("osd_draw_line: unknown type %d", line->type); } - XftColorFree(osd->dpy, osd->visual, osd->cmap, &fg_color); + XftColorFree(osd->dpy, osd->visual, osd->cmap, &osd->fg_color); XftColorFree(osd->dpy, osd->visual, osd->cmap, &outline_color); - XftColorFree(osd->dpy, osd->visual, osd->cmap, &mask_color); + XftColorFree(osd->dpy, osd->visual, osd->cmap, &osd->mask_color); } void osd_show(struct osd_state *osd) diff --git a/display.h b/display.h index 48ffb0b..953ef93 100644 --- a/display.h +++ b/display.h @@ -1,7 +1,7 @@ /* * On-screen Display * - * (c) 2013 Martin Mares + * (c) 2013--2014 Martin Mares */ #include @@ -24,6 +24,7 @@ struct osd_line { int outline_width; union { // Data dependent on type char text[OSD_MAX_LINE_LEN]; // in UTF-8 + unsigned int percent; // 0..100 for percentages and slider } u; // Used internally @@ -31,6 +32,9 @@ struct osd_line { int height; int x_pos; int y_pos; + int slider_unit; + int slider_space; + int slider_units; }; struct osd_state *osd_new(Display *dpy); diff --git a/osdd.c b/osdd.c index 2bfb8c3..ee34ded 100644 --- a/osdd.c +++ b/osdd.c @@ -1,7 +1,7 @@ /* * On-screen Display Daemon * - * (c) 2010--2013 Martin Mares + * (c) 2010--2014 Martin Mares */ #include @@ -25,7 +25,7 @@ static timestamp_t now; /*** Options ***/ -static char *font_name = "times-64"; +static char *font_name = "times-64:bold"; static char *default_color = "green"; static char *default_outline_color = "black"; static int default_outline_width = 2; @@ -161,13 +161,13 @@ display_msg(struct msg *msg) } else if (!strcmp(key, "percentage") || !strcmp(key, "percent")) { - // FIXME - // xosd_display(osd, row++, XOSD_percentage, atoi(val)); + l = osd_add_line(osd, OSD_TYPE_PERCENTAGE); + l->u.percent = atoi(val); } else if (!strcmp(key, "slider")) { - // FIXME - // xosd_display(osd, row++, XOSD_slider, atoi(val)); + l = osd_add_line(osd, OSD_TYPE_SLIDER); + l->u.percent = atoi(val); } else if (!strcmp(key, "duration")) msg->max_light = now + atoi(val); -- 2.39.5