all repos — tint2 @ 59c3761455cdc1822bf6214ad59b818a987d8feb

fork of the tint2 desktop panel for my custom setup - only minimized windows across all desktops for the taskbar

Refactor text rendering
o9000 mrovi9000@gmail.com
commit

59c3761455cdc1822bf6214ad59b818a987d8feb

parent

b50f5ecf3efccac5b81fcfe9a112e747e747a505

5 files changed, 292 insertions(+), 159 deletions(-)

jump to
M src/clock/clock.csrc/clock/clock.c

@@ -77,6 +77,9 @@ time1_has_font = FALSE;

time1_font_desc = NULL; time2_has_font = FALSE; time2_font_desc = NULL; + buf_time[0] = 0; + buf_date[0] = 0; + buf_tooltip[0] = 0; } void cleanup_clock()

@@ -111,31 +114,6 @@ stop_timeout(clock_timeout);

clock_timeout = NULL; } -void update_clocks_sec(void *arg) -{ - gettimeofday(&time_clock, 0); - if (time1_format) { - for (int i = 0; i < num_panels; i++) - panels[i].clock.area.resize_needed = 1; - } - schedule_panel_redraw(); -} - -void update_clocks_min(void *arg) -{ - // remember old_sec because after suspend/hibernate the clock should be updated directly, and not - // on next minute change - time_t old_sec = time_clock.tv_sec; - gettimeofday(&time_clock, 0); - if (time_clock.tv_sec % 60 == 0 || time_clock.tv_sec - old_sec > 60) { - if (time1_format) { - for (int i = 0; i < num_panels; i++) - panels[i].clock.area.resize_needed = 1; - } - schedule_panel_redraw(); - } -} - struct tm *clock_gettime_for_tz(const char *timezone) { if (timezone) {

@@ -152,6 +130,35 @@ return localtime(&time_clock.tv_sec);

} } +void update_clocks() +{ + if (time1_format) + strftime(buf_time, sizeof(buf_time), time1_format, clock_gettime_for_tz(time1_timezone)); + if (time2_format) + strftime(buf_date, sizeof(buf_date), time2_format, clock_gettime_for_tz(time2_timezone)); + if (time1_format || time2_format) { + for (int i = 0; i < num_panels; i++) + panels[i].clock.area.resize_needed = 1; + } + schedule_panel_redraw(); +} + +void update_clocks_sec(void *arg) +{ + gettimeofday(&time_clock, 0); + update_clocks(); +} + +void update_clocks_min(void *arg) +{ + // remember old_sec because after suspend/hibernate the clock should be updated directly, and not + // on next minute change + gettimeofday(&time_clock, 0); + time_t old_sec = time_clock.tv_sec; + if (time_clock.tv_sec % 60 == 0 || time_clock.tv_sec - old_sec > 60) + update_clocks(); +} + gboolean time_format_needs_sec_ticks(char *time_format) { if (!time_format)

@@ -205,6 +212,7 @@ if (time_tooltip_format) {

clock->area._get_tooltip_text = clock_get_tooltip; strftime(buf_tooltip, sizeof(buf_tooltip), time_tooltip_format, clock_gettime_for_tz(time_tooltip_timezone)); } + update_clocks_sec(NULL); } void clock_init_fonts()

@@ -251,138 +259,53 @@ int *date_height_ink,

int *date_height, int *date_width) { - Panel *panel = (Panel *)clock->area.panel; - int available_w, available_h; - if (panel_horizontal) { - available_w = panel->area.width; - available_h = clock->area.height - 2 * clock->area.paddingy - left_right_border_width(&clock->area); - } else { - available_w = clock->area.width - 2 * clock->area.paddingxlr - left_right_border_width(&clock->area); - available_h = panel->area.height; - } - - *date_height = *date_width = 0; - strftime(buf_time, sizeof(buf_time), time1_format, clock_gettime_for_tz(time1_timezone)); - get_text_size2(time1_font_desc, - time_height_ink, - time_height, - time_width, - available_h, - available_w, - buf_time, - strlen(buf_time), - PANGO_WRAP_WORD_CHAR, - PANGO_ELLIPSIZE_NONE, - FALSE); - if (time2_format) { - strftime(buf_date, sizeof(buf_date), time2_format, clock_gettime_for_tz(time2_timezone)); - get_text_size2(time2_font_desc, - date_height_ink, - date_height, - date_width, - available_h, - available_w, - buf_date, - strlen(buf_date), - PANGO_WRAP_WORD_CHAR, - PANGO_ELLIPSIZE_NONE, - FALSE); - } + area_compute_text_geometry(&clock->area, + buf_time, + time2_format ? buf_date : NULL, + time1_font_desc, + time2_font_desc, + time_height_ink, + time_height, + time_width, + date_height_ink, + date_height, + date_width); } int clock_compute_desired_size(void *obj) { Clock *clock = (Clock *)obj; - int time_height_ink, time_height, time_width, date_height_ink, date_height, date_width; - clock_compute_text_geometry(clock, - &time_height_ink, - &time_height, - &time_width, - &date_height_ink, - &date_height, - &date_width); - - if (panel_horizontal) { - int new_size = MAX(time_width, date_width) + 2 * clock->area.paddingxlr + left_right_border_width(&clock->area); - return new_size; - } else { - int new_size = time_height + date_height + 2 * clock->area.paddingxlr + top_bottom_border_width(&clock->area); - return new_size; - } + return text_area_compute_desired_size(&clock->area, + buf_time, + time2_format ? buf_date : NULL, + time1_font_desc, + time2_font_desc); } gboolean resize_clock(void *obj) { Clock *clock = (Clock *)obj; - gboolean result = FALSE; - - schedule_redraw(&clock->area); - - int time_height_ink, time_height, time_width, date_height_ink, date_height, date_width; - clock_compute_text_geometry(clock, - &time_height_ink, - &time_height, - &time_width, - &date_height_ink, - &date_height, - &date_width); - - int new_size = clock_compute_desired_size(clock); - if (panel_horizontal) { - if (new_size > clock->area.width || new_size < (clock->area.width - 6)) { - // we try to limit the number of resizes - clock->area.width = new_size + 1; - clock->time1_posy = (clock->area.height - time_height) / 2; - if (time2_format) { - clock->time1_posy -= (date_height) / 2; - clock->time2_posy = clock->time1_posy + time_height; - } - result = TRUE; - } - } else { - if (new_size != clock->area.height) { - // we try to limit the number of resizes - clock->area.height = new_size; - clock->time1_posy = (clock->area.height - time_height) / 2; - if (time2_format) { - clock->time1_posy -= (date_height) / 2; - clock->time2_posy = clock->time1_posy + time_height; - } - result = TRUE; - } - } - - return result; + return resize_text_area(&clock->area, + buf_time, + time2_format ? buf_date : NULL, + time1_font_desc, + time2_font_desc, + &clock->time1_posy, + &clock->time2_posy); } void draw_clock(void *obj, cairo_t *c) { - Clock *clock = obj; - PangoLayout *layout = pango_cairo_create_layout(c); - - pango_layout_set_font_description(layout, time1_font_desc); - pango_layout_set_width(layout, clock->area.width * PANGO_SCALE); - pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); - pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); - pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE); - pango_layout_set_text(layout, buf_time, strlen(buf_time)); - - cairo_set_source_rgba(c, clock->font.rgb[0], clock->font.rgb[1], clock->font.rgb[2], clock->font.alpha); - - pango_cairo_update_layout(c, layout); - draw_text(layout, c, 0, clock->time1_posy, &clock->font, ((Panel *)clock->area.panel)->font_shadow); - - if (time2_format) { - pango_layout_set_font_description(layout, time2_font_desc); - pango_layout_set_indent(layout, 0); - pango_layout_set_text(layout, buf_date, strlen(buf_date)); - pango_layout_set_width(layout, clock->area.width * PANGO_SCALE); - - pango_cairo_update_layout(c, layout); - draw_text(layout, c, 0, clock->time2_posy, &clock->font, ((Panel *)clock->area.panel)->font_shadow); - } - - g_object_unref(layout); + Clock *clock = (Clock *)obj; + draw_text_area(&clock->area, + c, + buf_time, + time2_format ? buf_date : NULL, + time1_font_desc, + time2_font_desc, + clock->time1_posy, + clock->time2_posy, + &clock->font); } void clock_dump_geometry(void *obj, int indent)
M src/util/area.csrc/util/area.c

@@ -883,6 +883,180 @@ area_dump_geometry((Area *)l->data, indent);

} } +void area_compute_text_geometry(Area *area, + const char *line1, + const char *line2, + PangoFontDescription *line1_font_desc, + PangoFontDescription *line2_font_desc, + int *line1_height_ink, + int *line1_height, + int *line1_width, + int *line2_height_ink, + int *line2_height, + int *line2_width) +{ + Panel *panel = (Panel *)area->panel; + int available_w, available_h; + if (panel_horizontal) { + available_w = panel->area.width; + available_h = area->height - 2 * area->paddingy - left_right_border_width(area); + } else { + available_w = area->width - 2 * area->paddingxlr - left_right_border_width(area); + available_h = panel->area.height; + } + + if (line1 && line1[0]) + get_text_size2(line1_font_desc, + line1_height_ink, + line1_height, + line1_width, + available_h, + available_w, + line1, + strlen(line1), + PANGO_WRAP_WORD_CHAR, + PANGO_ELLIPSIZE_NONE, + FALSE); + else + *line1_width = *line1_height_ink = *line1_height = 0; + + if (line2 && line2[0]) + get_text_size2(line2_font_desc, + line2_height_ink, + line2_height, + line2_width, + available_h, + available_w, + line2, + strlen(line2), + PANGO_WRAP_WORD_CHAR, + PANGO_ELLIPSIZE_NONE, + FALSE); + else + *line2_width = *line2_height_ink = *line2_height = 0; +} + +int text_area_compute_desired_size(Area *area, + const char *line1, + const char *line2, + PangoFontDescription *line1_font_desc, + PangoFontDescription *line2_font_desc) +{ + int line1_height_ink, line1_height, line1_width, line2_height_ink, line2_height, line2_width; + area_compute_text_geometry(area, + line1, + line2, + line1_font_desc, + line2_font_desc, + &line1_height_ink, + &line1_height, + &line1_width, + &line2_height_ink, + &line2_height, + &line2_width); + + if (panel_horizontal) { + int new_size = MAX(line1_width, line2_width) + 2 * area->paddingxlr + left_right_border_width(area); + return new_size; + } else { + int new_size = line1_height + line2_height + 2 * area->paddingxlr + top_bottom_border_width(area); + return new_size; + } +} + +gboolean resize_text_area(Area *area, + const char *line1, + const char *line2, + PangoFontDescription *line1_font_desc, + PangoFontDescription *line2_font_desc, + int *line1_posy, + int *line2_posy) +{ + gboolean result = FALSE; + + schedule_redraw(area); + + int line1_height_ink, line1_height, line1_width; + int line2_height_ink, line2_height, line2_width; + area_compute_text_geometry(area, + line1, + line2, + line1_font_desc, + line2_font_desc, + &line1_height_ink, + &line1_height, + &line1_width, + &line2_height_ink, + &line2_height, + &line2_width); + + int new_size = text_area_compute_desired_size(area, + line1, + line2, + line1_font_desc, + line2_font_desc); + if (panel_horizontal) { + if (new_size > area->width || new_size < (area->width - 6)) { + // we try to limit the number of resizes + area->width = new_size + 1; + *line1_posy = (area->height - line1_height) / 2; + if (line2) { + *line1_posy -= (line2_height) / 2; + *line2_posy = *line1_posy + line1_height; + } + result = TRUE; + } + } else { + if (new_size != area->height) { + // we try to limit the number of resizes + area->height = new_size; + *line1_posy = (area->height - line1_height) / 2; + if (line2) { + *line1_posy -= (line2_height) / 2; + *line2_posy = *line1_posy + line1_height; + } + result = TRUE; + } + } + + return result; +} + +void draw_text_area(Area *area, + cairo_t *c, + const char *line1, + const char *line2, + PangoFontDescription *line1_font_desc, + PangoFontDescription *line2_font_desc, + int line1_posy, + int line2_posy, + Color *color) +{ + PangoLayout *layout = pango_cairo_create_layout(c); + pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); + pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); + pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE); + pango_layout_set_width(layout, area->width * PANGO_SCALE); + cairo_set_source_rgba(c, color->rgb[0], color->rgb[1], color->rgb[2], color->alpha); + + if (line1 && line1[0]) { + pango_layout_set_font_description(layout, line1_font_desc); + pango_layout_set_text(layout, line1, strlen(line1)); + pango_cairo_update_layout(c, layout); + draw_text(layout, c, 0, line1_posy, color, ((Panel *)area->panel)->font_shadow); + } + + if (line2 && line2[0]) { + pango_layout_set_font_description(layout, line2_font_desc); + pango_layout_set_indent(layout, 0); + pango_layout_set_text(layout, line2, strlen(line2)); + pango_cairo_update_layout(c, layout); + draw_text(layout, c, 0, line2_posy, color, ((Panel *)area->panel)->font_shadow); + } + + g_object_unref(layout); +} + Area *compute_element_area(Area *area, Element element) { if (element == ELEMENT_SELF)
M src/util/area.hsrc/util/area.h

@@ -263,6 +263,39 @@

int compute_desired_size(Area *a); int container_compute_desired_size(Area *a); +void area_compute_text_geometry(Area *area, + const char *line1, + const char *line2, + PangoFontDescription *line1_font_desc, + PangoFontDescription *line2_font_desc, + int *line1_height_ink, + int *line1_height, + int *line1_width, + int *line2_height_ink, + int *line2_height, + int *line2_width); +int text_area_compute_desired_size(Area *area, + const char *line1, + const char *line2, + PangoFontDescription *line1_font_desc, + PangoFontDescription *line2_font_desc); +gboolean resize_text_area(Area *area, + const char *line1, + const char *line2, + PangoFontDescription *line1_font_desc, + PangoFontDescription *line2_font_desc, + int *line1_posy, + int *line2_posy); +void draw_text_area(Area *area, + cairo_t *c, + const char *line1, + const char *line2, + PangoFontDescription *line1_font_desc, + PangoFontDescription *line2_font_desc, + int line1_posy, + int line2_posy, + Color *color); + int left_border_width(Area *a); int right_border_width(Area *a); int left_right_border_width(Area *a);
M src/util/common.csrc/util/common.c

@@ -736,35 +736,38 @@ XRenderFillRectangle(server.display, PictOpSrc, pict, &col, x, y, w, h);

XRenderFreePicture(server.display, pict); } -void get_text_size2(PangoFontDescription *font, +void get_text_size2(const PangoFontDescription *font, int *height_ink, int *height, int *width, - int panel_height, - int panel_width, - char *text, - int len, + int available_height, + int available_width, + const char *text, + int text_len, PangoWrapMode wrap, PangoEllipsizeMode ellipsis, gboolean markup) { PangoRectangle rect_ink, rect; - Pixmap pmap = XCreatePixmap(server.display, server.root_win, panel_height, panel_width, server.depth); + available_width = MAX(0, available_width); + available_height = MAX(0, available_height); + Pixmap pmap = XCreatePixmap(server.display, server.root_win, available_height, available_width, server.depth); - cairo_surface_t *cs = cairo_xlib_surface_create(server.display, pmap, server.visual, panel_height, panel_width); + cairo_surface_t *cs = cairo_xlib_surface_create(server.display, pmap, server.visual, available_height, available_width); cairo_t *c = cairo_create(cs); PangoLayout *layout = pango_cairo_create_layout(c); - pango_layout_set_width(layout, panel_width * PANGO_SCALE); - pango_layout_set_height(layout, panel_height * PANGO_SCALE); + pango_layout_set_width(layout, available_width * PANGO_SCALE); + pango_layout_set_height(layout, available_height * PANGO_SCALE); pango_layout_set_wrap(layout, wrap); pango_layout_set_ellipsize(layout, ellipsis); pango_layout_set_font_description(layout, font); + text_len = MAX(0, text_len); if (!markup) - pango_layout_set_text(layout, text, len); + pango_layout_set_text(layout, text, text_len); else - pango_layout_set_markup(layout, text, len); + pango_layout_set_markup(layout, text, text_len); pango_layout_get_pixel_extents(layout, &rect_ink, &rect); *height_ink = rect_ink.height;
M src/util/common.hsrc/util/common.h

@@ -95,14 +95,14 @@

// Renders the current Imlib image to a drawable. Wrapper around imlib_render_image_on_drawable. void render_image(Drawable d, int x, int y); -void get_text_size2(PangoFontDescription *font, +void get_text_size2(const PangoFontDescription *font, int *height_ink, int *height, int *width, - int panel_height, - int panel_with, - char *text, - int len, + int available_height, + int available_with, + const char *text, + int text_len, PangoWrapMode wrap, PangoEllipsizeMode ellipsis, gboolean markup);