diff --git a/bar/bar.c b/bar/bar.c index f0dc1d8..d763cc3 100644 --- a/bar/bar.c +++ b/bar/bar.c @@ -41,7 +41,7 @@ accum_widths( { for (size_t i = 0; i < s->count; i++) { struct exposable *e = s->exps[i]; - if (e->height > 0) + if (e->width > 0) *out = act(*out, b->left_spacing + e->width + b->right_spacing); } } @@ -62,7 +62,7 @@ accum_heights(const struct section *s, const struct private *b, if (e->height > 0) *out = act(*out, b->top_spacing + e->height + b->bottom_spacing); } - } +} /* Add action */ @@ -87,10 +87,12 @@ larger(int a, int b) static void calculate_widths(const struct private *b, int *left, int *center, int *right) { - *left = *center = *right = 0; - accum_widths(&(b->left), b, left, &add); - accum_widths(&(b->center), b, center, &add); - accum_widths(&(b->right), b, right, &add); + *left = 0; + *center = 0; + *right = 0; + accum_widths(&b->left, b, left, &add); + accum_widths(&b->center, b, center, &add); + accum_widths(&b->right, b, right, &add); /* No spacing on the edges (that's what the margins are for) */ if (*left > 0) @@ -100,12 +102,13 @@ calculate_widths(const struct private *b, int *left, int *center, int *right) if (*right > 0) *right -= b->left_spacing + b->right_spacing; + assert(*left >= 0); assert(*center >= 0); assert(*right >= 0); } -#if 0 + /* * Calculate total height of left/center/right groups. * Note: begin_expose() must have been called @@ -117,9 +120,9 @@ calculate_heights (const struct private *b, int *top, int *middle, int *bottom) *middle = 0; *bottom = 0; - accum_heights(&(b->left), b, top, &add); - accum_heights(&(b->center), b, middle, &add); - accum_heights(&(b->right), b, bottom, &add); + accum_heights(&b->left, b, top, &add); + accum_heights(&b->center, b, middle, &add); + accum_heights(&b->right, b, bottom, &add); /* No spacing on the edges (that's what the margins are for) */ if (*top > 0) @@ -133,7 +136,7 @@ calculate_heights (const struct private *b, int *top, int *middle, int *bottom) assert(*middle >= 0); assert(*bottom >= 0); } -#endif + /* * Calculate the minimum width the bar needs to be to show all particles. * This assumes the bar is at the left or right of screen. @@ -144,9 +147,9 @@ min_bar_width (const struct private *b) { int min = 0; - accum_widths(&(b->left), b, &min, &larger); - accum_widths(&(b->center), b, &min, &larger); - accum_widths(&(b->right), b, &min, &larger); + accum_widths(&b->left, b, &min, &larger); + accum_widths(&b->center, b, &min, &larger); + accum_widths(&b->right, b, &min, &larger); return min; } @@ -159,12 +162,11 @@ min_bar_width (const struct private *b) static int min_bar_height (const struct private *b) { - LOG_INFO("Mining"); int min = 0; - accum_heights(&(b->left), b, &min, &larger); - accum_heights(&(b->center), b, &min, &larger); - accum_heights(&(b->right), b, &min, &larger); + accum_heights(&b->left, b, &min, &larger); + accum_heights(&b->center, b, &min, &larger); + accum_heights(&b->right, b, &min, &larger); return min; } @@ -186,21 +188,17 @@ begin_expose_mods(const struct section *s) static void bar_recalc_size(struct private *bar) { - LOG_DBG("Bar width auto? %s", - bar->width < 0 ? "yes" : "no"); - LOG_DBG("Bar height auto? %s", - bar->height < 0 ? "yes" : "no"); - - begin_expose_mods(&(bar->left)); - begin_expose_mods(&(bar->center)); - begin_expose_mods(&(bar->right)); + begin_expose_mods(&bar->left); + begin_expose_mods(&bar->center); + begin_expose_mods(&bar->right); if (bar->height < 0){ if ((bar->location & (BAR_TOP | BAR_BOTTOM)) == bar->location) bar->height_with_border = - min_bar_height(bar) + bar->border.top_width + bar->border.bottom_width; + min_bar_height(bar) + bar->border.top_width + bar->border.bottom_width + bar->top_margin + bar->bottom_margin; else bar->height_with_border = 0; + LOG_INFO("auto height: %d", bar->height_with_border); } else bar->height_with_border = bar->height + bar->border.top_width + bar->border.bottom_width; @@ -208,17 +206,35 @@ bar_recalc_size(struct private *bar) if (bar->width < 0){ if ((bar->location & (BAR_LEFT | BAR_RIGHT)) == bar->location) bar->width_with_border = - min_bar_width(bar) + bar->border.left_width + bar->border.right_width; + min_bar_width(bar) + bar->border.left_width + bar->border.right_width + bar->left_margin + bar->right_margin; else bar->width_with_border = 0; + LOG_INFO("auto width: %d", bar->width_with_border); }else bar->width_with_border = bar->width + bar->border.top_width + bar->border.bottom_width; - - LOG_DBG("Bar width calculated size %d", - bar->width); - LOG_DBG("Bar height calculated size %d", - bar->height); +} + +static bool +is_vertical (const struct bar *_bar) +{ + const struct private *bar = _bar->private; + return bar->location == BAR_LEFT || bar->location == BAR_RIGHT; +} + +static void +bar_expose_section ( + const struct section *s, const struct private *b, + pixman_image_t *pix, int x, int y, bool vertical) +{ + for (size_t i = 0; i < s->count; i++) { + const struct exposable *e = s->exps[i]; + e->expose(e, pix, x, y, b->height); + if (vertical && e->height > 0) + y += b->top_spacing + e->height + b->bottom_spacing; + else if (!vertical && e->width > 0) + x += b->left_spacing + e->width + b->right_spacing; + } } static void @@ -253,52 +269,56 @@ expose(const struct bar *_bar) bar->width_with_border - bar->border.left_width - bar->border.right_width, bar->border.bottom_width}, }); - - int left_width, center_width, right_width; - calculate_widths(bar, &left_width, ¢er_width, &right_width); -# if 0 - int y = bar->border.top_width; - int x = bar->border.left_width + bar->left_margin - bar->left_spacing; +/** pixman_region32_t clip; pixman_region32_init_rect( &clip, bar->border.left_width + bar->left_margin, - bar->border.top_width, - (bar->width - + bar->border.top_width + bar->border.top_margin, + (bar->width_with_border - bar->left_margin - bar->right_margin - bar->border.left_width - bar->border.right_width), - bar->height); + (bar->height_with_border - + bar->top_margin - bar->bottom_margin - + bar->border.top_width - bar->border.bottom_width)); pixman_image_set_clip_region32(pix, &clip); - pixman_region32_fini(&clip); + pixman_region32_fini(&clip);*/ - for (size_t i = 0; i < bar->left.count; i++) { - const struct exposable *e = bar->left.exps[i]; - e->expose(e, pix, x + bar->left_spacing, y, bar->height); - if (e->width > 0) - x += bar->left_spacing + e->width + bar->right_spacing; - } + int left_width, center_width, right_width; + calculate_widths(bar, &left_width, ¢er_width, &right_width); - x = bar->width / 2 - center_width / 2 - bar->left_spacing; - for (size_t i = 0; i < bar->center.count; i++) { - const struct exposable *e = bar->center.exps[i]; - e->expose(e, pix, x + bar->left_spacing, y, bar->height); - if (e->width > 0) - x += bar->left_spacing + e->width + bar->right_spacing; - } + int top_height, center_height, bottom_height; + calculate_heights(bar, &top_height, ¢er_height, &bottom_height); + LOG_INFO("Widths: %d %d %d", top_height, center_height, bottom_height); - x = bar->width - ( - right_width + - bar->left_spacing + - bar->right_margin + - bar->border.right_width); + bool virt = is_vertical(_bar); + + int y = bar->border.top_width + bar->border.top_margin; + int x = bar->border.left_width + bar->left_margin; + + bar_expose_section(&bar->left, bar, pix, x, y, virt); + + if (virt) + y = bar->height / 2 - center_height / 2 - bar->top_spacing; + else + x = bar->width / 2 - center_width / 2 - bar->left_spacing; + bar_expose_section(&bar->center, bar, pix, x, y, virt); + + if(virt) + y = bar->height - ( + bottom_height + + bar->top_spacing + + bar->bottom_margin + + bar->border.bottom_width); + else + x = bar->width - ( + right_width + + bar->left_spacing + + bar->right_margin + + bar->border.right_width); + + bar_expose_section(&bar->right, bar, pix, x, y, virt); - for (size_t i = 0; i < bar->right.count; i++) { - const struct exposable *e = bar->right.exps[i]; - e->expose(e, pix, x + bar->left_spacing, y, bar->height); - if (e->width > 0) - x += bar->left_spacing + e->width + bar->right_spacing; - } -#endif bar->backend.iface->commit(_bar); } @@ -643,6 +663,7 @@ bar_new(const struct bar_config *config) bar->destroy = &destroy; bar->refresh = &refresh; bar->set_cursor = &set_cursor; + bar->is_vertical = &is_vertical; bar->output_name = &output_name; for (size_t i = 0; i < priv->left.count; i++) diff --git a/bar/bar.h b/bar/bar.h index 54529a1..7ae21ae 100644 --- a/bar/bar.h +++ b/bar/bar.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "../color.h" #include "../font-shaping.h" #include "../module.h" @@ -14,6 +16,8 @@ struct bar { void (*refresh)(const struct bar *bar); void (*set_cursor)(struct bar *bar, const char *cursor); + bool (*is_vertical)(const struct bar *bar); + const char *(*output_name)(const struct bar *bar); }; diff --git a/bar/wayland.c b/bar/wayland.c index 835035a..98a5c97 100644 --- a/bar/wayland.c +++ b/bar/wayland.c @@ -1062,8 +1062,8 @@ update_size(struct wayland_backend *backend) } LOG_INFO("backend size: %dx%d", backend->width, backend->height); - bar->width_with_border = backend->width; - bar->height_with_border = backend->height; + bar->width = backend->width; + bar->height = backend->height; if (bar->location & (BAR_TOP | BAR_BOTTOM)) { zwlr_layer_surface_v1_set_exclusive_zone( @@ -1092,8 +1092,8 @@ update_size(struct wayland_backend *backend) wl_surface_commit(backend->surface); // TODO: Figure out why not setting width & height // make the bar fail to appear. Don't want to have to do this - bar->width = backend->width - (bar->border.left_width + bar->border.right_width); - bar->height = backend->height - (bar->border.top_width + bar->border.bottom_width); + bar->width_with_border = backend->width; + bar->height_with_border = backend->height; /* Reload buffers */ if (backend->next_buffer != NULL) @@ -1466,7 +1466,7 @@ static void refresh(const struct bar *_bar) { const struct private *bar = _bar->private; - const struct wayland_backend *backend = bar->backend.data; + struct wayland_backend *backend = bar->backend.data; if (write(backend->pipe_fds[1], &(uint8_t){1}, sizeof(uint8_t)) != sizeof(uint8_t)) diff --git a/main.c b/main.c index 7aab81a..85bdcaf 100644 --- a/main.c +++ b/main.c @@ -189,7 +189,7 @@ main(int argc, char *const *argv) {"help", no_argument, 0, 'h'}, {NULL, no_argument, 0, 0}, }; - + bool unlink_pid_file = false; const char *pid_file = NULL; diff --git a/modules/cpu.c b/modules/cpu.c index 455d45d..46cfde4 100644 --- a/modules/cpu.c +++ b/modules/cpu.c @@ -207,7 +207,7 @@ content(struct module *mod) } mtx_unlock(&mod->lock); - return dynlist_exposable_new(parts, list_count, 0, 0); + return dynlist_exposable_new(parts, list_count, mod->bar->is_vertical(mod->bar), 0, 0); } static int diff --git a/modules/disk-io.c b/modules/disk-io.c index 7bf48e8..d4871cb 100644 --- a/modules/disk-io.c +++ b/modules/disk-io.c @@ -259,7 +259,7 @@ content(struct module *mod) tag_set_destroy(&tags); mtx_unlock(&mod->lock); - return dynlist_exposable_new(tag_parts, p->devices.length + 1, 0, 0); + return dynlist_exposable_new(tag_parts, p->devices.length + 1, mod->bar->is_vertical(mod->bar), 0, 0); } static int diff --git a/modules/dwl.c b/modules/dwl.c index 5fa1023..eea05cc 100644 --- a/modules/dwl.c +++ b/modules/dwl.c @@ -120,7 +120,7 @@ content(struct module *module) tag_set_destroy(&tags); mtx_unlock(&module->lock); - return dynlist_exposable_new(exposable, i, 0, 0); + return dynlist_exposable_new(exposable, module->bar->is_vertical(module->bar), i, 0, 0); } static struct dwl_tag * diff --git a/modules/foreign-toplevel.c b/modules/foreign-toplevel.c index d454a39..9de4a46 100644 --- a/modules/foreign-toplevel.c +++ b/modules/foreign-toplevel.c @@ -149,7 +149,7 @@ content(struct module *mod) } mtx_unlock(&mod->lock); - return dynlist_exposable_new(toplevels, show_count, 0, 0); + return dynlist_exposable_new(toplevels, show_count, mod->bar->is_vertical(mod->bar), 0, 0); } static bool diff --git a/modules/i3.c b/modules/i3.c index 96e215a..fa531a5 100644 --- a/modules/i3.c +++ b/modules/i3.c @@ -904,7 +904,7 @@ content(struct module *mod) mtx_unlock(&mod->lock); return dynlist_exposable_new( - particles, particle_count, m->left_spacing, m->right_spacing); + particles, particle_count, mod->bar->is_vertical(mod->bar), m->left_spacing, m->right_spacing); } /* Maps workspace name to a content particle. */ diff --git a/modules/pipewire.c b/modules/pipewire.c index 0cc641d..ef400aa 100644 --- a/modules/pipewire.c +++ b/modules/pipewire.c @@ -856,7 +856,7 @@ content(struct module *module) struct private *private = module->private; if (private->data == NULL) - return dynlist_exposable_new(NULL, 0, 0, 0); + return dynlist_exposable_new(NULL, 0, module->bar->is_vertical(module->bar), 0, 0); mtx_lock(&module->lock); @@ -915,7 +915,7 @@ content(struct module *module) mtx_unlock(&module->lock); - return dynlist_exposable_new(exposables, exposables_length, 0, 0); + return dynlist_exposable_new(exposables, exposables_length, module->bar->is_vertical(module->bar), 0, 0); } static int diff --git a/modules/removables.c b/modules/removables.c index 4d1d508..5a65c87 100644 --- a/modules/removables.c +++ b/modules/removables.c @@ -158,7 +158,7 @@ content(struct module *mod) tll_free(partitions); return dynlist_exposable_new( - exposables, idx, m->left_spacing, m->right_spacing); + exposables, idx, mod->bar->is_vertical(mod->bar), m->left_spacing, m->right_spacing); } static void diff --git a/modules/river.c b/modules/river.c index 2273166..f7e2a63 100644 --- a/modules/river.c +++ b/modules/river.c @@ -178,7 +178,7 @@ content(struct module *mod) } mtx_unlock(&m->mod->lock); - return dynlist_exposable_new(tag_parts, 32 + seat_count, 0, 0); + return dynlist_exposable_new(tag_parts, 32 + seat_count, mod->bar->is_vertical(mod->bar), 0, 0); } static bool diff --git a/modules/sway-xkb.c b/modules/sway-xkb.c index 96d8388..0c2a914 100644 --- a/modules/sway-xkb.c +++ b/modules/sway-xkb.c @@ -90,7 +90,7 @@ content(struct module *mod) mtx_unlock(&mod->lock); return dynlist_exposable_new( - particles, m->num_existing_inputs, m->left_spacing, m->right_spacing); + particles, m->num_existing_inputs, mod->bar->is_vertical(mod->bar), m->left_spacing, m->right_spacing); } static bool diff --git a/particle.c b/particle.c index fe1d138..edcce7a 100644 --- a/particle.c +++ b/particle.c @@ -64,11 +64,11 @@ exposable_default_destroy(struct exposable *exposable) void exposable_render_deco(const struct exposable *exposable, - pixman_image_t *pix, int x, int y, int height) + pixman_image_t *pix, int x, int y) { const struct deco *deco = exposable->particle->deco; if (deco != NULL) - deco->expose(deco, pix, x, y, exposable->width, height); + deco->expose(deco, pix, x, y, exposable->width, exposable->height); } diff --git a/particle.h b/particle.h index 2cfecb6..879f2db 100644 --- a/particle.h +++ b/particle.h @@ -32,6 +32,7 @@ struct particle { void *private; int left_margin, right_margin; + int top_margin, bottom_margin; bool have_on_click_template; char *on_click_templates[MOUSE_BTN_COUNT]; @@ -58,6 +59,7 @@ struct exposable { void (*destroy)(struct exposable *exposable); int (*begin_expose)(struct exposable *exposable); + // TODO: remove 'height' from expose now that we have the internal variable void (*expose)(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int height); @@ -76,7 +78,7 @@ struct exposable *exposable_common_new( const struct particle *particle, const struct tag_set *tags); void exposable_default_destroy(struct exposable *exposable); void exposable_render_deco( - const struct exposable *exposable, pixman_image_t *pix, int x, int y, int height); + const struct exposable *exposable, pixman_image_t *pix, int x, int y); void exposable_default_on_mouse( struct exposable *exposable, struct bar *bar, diff --git a/particles/dynlist.c b/particles/dynlist.c index 5b64dbe..04e2f51 100644 --- a/particles/dynlist.c +++ b/particles/dynlist.c @@ -8,12 +8,15 @@ #include "../particle.h" struct private { - int left_spacing; - int right_spacing; + int pre_spacing; + int post_spacing; + + bool vertical; struct exposable **exposables; size_t count; int *widths; + int *heights; }; static void @@ -27,6 +30,7 @@ dynlist_destroy(struct exposable *exposable) free(e->exposables); free(e->widths); + free(e->heights); free(e); free(exposable); } @@ -35,26 +39,41 @@ static int dynlist_begin_expose(struct exposable *exposable) { const struct private *e = exposable->private; - + exposable->width = 0; + exposable->height = 0; bool have_at_least_one = false; for (size_t i = 0; i < e->count; i++) { struct exposable *ee = e->exposables[i]; - e->widths[i] = ee->begin_expose(ee); + ee->begin_expose(ee); + e->widths[i] = ee->width; + e->heights[i] = ee->height; - assert(e->widths[i] >= 0); + assert(e->widths[i] >= 0 && e->heights[i] >= 0); - if (e->widths[i] > 0) { - exposable->width += e->left_spacing + e->widths[i] + e->right_spacing; + if (e->widths[i] > 0 && e->heights[i] > 0) { + if (e->vertical) { + exposable->height += e->pre_spacing + e->heights[i] + e->post_spacing; + if (e->widths[i] > exposable->width) + exposable->width = e->widths[i]; + } else { + exposable->width += e->pre_spacing + e->widths[i] + e->post_spacing; + if (e->heights[i] > exposable->height) + exposable->height = e->heights[i]; + } have_at_least_one = true; } } - if (have_at_least_one) - exposable->width -= e->left_spacing + e->right_spacing; + if (have_at_least_one) { + if (e->vertical) + exposable->height -= e->pre_spacing + e->post_spacing; + else + exposable->width -= e->pre_spacing + e->post_spacing; + } else - assert(exposable->width == 0); + assert(exposable->width == 0 || exposable->height == 0); return exposable->width; } @@ -63,15 +82,25 @@ dynlist_expose(const struct exposable *exposable, pixman_image_t *pix, int x, in { const struct private *e = exposable->private; - int left_spacing = e->left_spacing; - int right_spacing = e->right_spacing; + int pre_spacing = e->pre_spacing; + int post_spacing = e->post_spacing; - x -= left_spacing; + if (e->vertical) { + y -= pre_spacing; - for (size_t i = 0; i < e->count; i++) { - const struct exposable *ee = e->exposables[i]; - ee->expose(ee, pix, x + left_spacing, y, height); - x += left_spacing + e->widths[i] + right_spacing; + for (size_t i = 0; i < e->count; i++) { + const struct exposable *ee = e->exposables[i]; + ee->expose(ee, pix, x, y + pre_spacing, height); + y += pre_spacing + e->heights[i] + post_spacing; + } + } else { + x -= pre_spacing; + + for (size_t i = 0; i < e->count; i++) { + const struct exposable *ee = e->exposables[i]; + ee->expose(ee, pix, x + pre_spacing, y, height); + x += pre_spacing + e->widths[i] + post_spacing; + } } } @@ -96,7 +125,7 @@ on_mouse(struct exposable *exposable, struct bar *bar, return; } - px += e->left_spacing + e->exposables[i]->width + e->right_spacing; + px += e->pre_spacing + e->exposables[i]->width + e->post_spacing; } LOG_DBG("on_mouse missed all sub-particles"); @@ -104,15 +133,17 @@ on_mouse(struct exposable *exposable, struct bar *bar, } struct exposable * -dynlist_exposable_new(struct exposable **exposables, size_t count, - int left_spacing, int right_spacing) +dynlist_exposable_new(struct exposable **exposables, size_t count, bool vertical, + int pre_spacing, int post_spacing) { struct private *e = calloc(1, sizeof(*e)); e->count = count; + e->vertical = vertical; e->exposables = malloc(count * sizeof(e->exposables[0])); e->widths = calloc(count, sizeof(e->widths[0])); - e->left_spacing = left_spacing; - e->right_spacing = right_spacing; + e->heights = calloc(count, sizeof(e->heights[0])); + e->pre_spacing = pre_spacing; + e->post_spacing = post_spacing; for (size_t i = 0; i < count; i++) e->exposables[i] = exposables[i]; diff --git a/particles/dynlist.h b/particles/dynlist.h index 4867997..589548e 100644 --- a/particles/dynlist.h +++ b/particles/dynlist.h @@ -1,7 +1,8 @@ #pragma once #include +#include struct particle; struct exposable *dynlist_exposable_new( - struct exposable **exposables, size_t count, int left_spacing, int right_spacing); + struct exposable **exposables, size_t count, bool vertical, int pre_spacing, int post_spacing); diff --git a/particles/empty.c b/particles/empty.c index 5c0be16..436a45e 100644 --- a/particles/empty.c +++ b/particles/empty.c @@ -10,13 +10,15 @@ begin_expose(struct exposable *exposable) { exposable->width = exposable->particle->left_margin + exposable->particle->right_margin; + exposable->height = exposable->particle->top_margin + + exposable->particle->bottom_margin; return exposable->width; } static void expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int height) { - exposable_render_deco(exposable, pix, x, y, height); + exposable_render_deco(exposable, pix, x, y); } static struct exposable * diff --git a/particles/list.c b/particles/list.c index a2c37c6..af7f864 100644 --- a/particles/list.c +++ b/particles/list.c @@ -1,4 +1,5 @@ #include +#include #define LOG_MODULE "list" #define LOG_ENABLE_DBG 0 @@ -11,14 +12,17 @@ struct private { struct particle **particles; size_t count; - int left_spacing, right_spacing; + bool vertical; + int pre_spacing, post_spacing; }; struct eprivate { struct exposable **exposables; int *widths; + int *heights; + bool vertical; size_t count; - int left_spacing, right_spacing; + int pre_spacing, post_spacing; }; @@ -31,6 +35,7 @@ exposable_destroy(struct exposable *exposable) free(e->exposables); free(e->widths); + free(e->heights); free(e); exposable_default_destroy(exposable); } @@ -42,25 +47,39 @@ begin_expose(struct exposable *exposable) bool have_at_least_one = false; exposable->width = 0; + exposable->height = 0; for (size_t i = 0; i < e->count; i++) { struct exposable *ee = e->exposables[i]; - e->widths[i] = ee->begin_expose(ee); + ee->begin_expose(ee); + e->widths[i] = ee->width; + e->heights[i] = ee->height; - assert(e->widths[i] >= 0); + assert(e->widths[i] >= 0 && e->heights[i] >= 0); - if (e->widths[i] > 0) { - exposable->width += e->left_spacing + e->widths[i] + e->right_spacing; + if (e->widths[i] > 0 && e->heights[i] > 0) { + if (e->vertical) { + exposable->height += e->pre_spacing + e->heights[i] + e->post_spacing; + if (e->widths[i] > exposable->width) + exposable->width = e->widths[i]; + } else { + exposable->width += e->pre_spacing + e->widths[i] + e->post_spacing; + if (e->heights[i] > exposable->height) + exposable->height = e->heights[i]; + } have_at_least_one = true; } } if (have_at_least_one) { - exposable->width -= e->left_spacing + e->right_spacing; - exposable->width += exposable->particle->left_margin; - exposable->width += exposable->particle->right_margin; + if(e->vertical) + exposable->width -= e->pre_spacing + e->post_spacing; + else + exposable->height -= e->pre_spacing + e->post_spacing; + exposable->width += exposable->particle->left_margin + exposable->particle->right_margin; + exposable->height += exposable->particle->top_margin + exposable->particle->bottom_margin; } else - assert(exposable->width == 0); + assert(exposable->width == 0 && exposable->height == 0); return exposable->width; } @@ -70,20 +89,31 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int { const struct eprivate *e = exposable->private; - exposable_render_deco(exposable, pix, x, y, height); + exposable_render_deco(exposable, pix, x, y); - int left_margin = exposable->particle->left_margin; - int left_spacing = e->left_spacing; - int right_spacing = e->right_spacing; + int pre_spacing = e->pre_spacing; + int post_spacing = e->post_spacing; + x += exposable->particle->left_margin; + y += exposable->particle->top_margin; - x += left_margin - left_spacing; - for (size_t i = 0; i < e->count; i++) { - const struct exposable *ee = e->exposables[i]; - ee->expose(ee, pix, x + left_spacing, y, height); - x += left_spacing + e->widths[i] + right_spacing; + if (e->vertical) { + y -= pre_spacing; + for (size_t i = 0; i < e->count; i++) { + const struct exposable *ee = e->exposables[i]; + ee->expose(ee, pix, x, y + pre_spacing, height); + x += pre_spacing + e->heights[i] + post_spacing; + } + } else { + x -= pre_spacing; + for (size_t i = 0; i < e->count; i++) { + const struct exposable *ee = e->exposables[i]; + ee->expose(ee, pix, x + pre_spacing, y, height); + x += pre_spacing + e->widths[i] + post_spacing; + } } } +// TODO: update for vertical lists static void on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y) @@ -110,7 +140,7 @@ on_mouse(struct exposable *exposable, struct bar *bar, return; } - px += e->left_spacing + e->exposables[i]->width + e->right_spacing; + px += e->pre_spacing + e->exposables[i]->width + e->post_spacing; } /* We're between sub-particles (or in the left/right margin) */ @@ -125,9 +155,11 @@ instantiate(const struct particle *particle, const struct tag_set *tags) struct eprivate *e = calloc(1, sizeof(*e)); e->exposables = malloc(p->count * sizeof(*e->exposables)); e->widths = calloc(p->count, sizeof(*e->widths)); + e->heights = calloc(p->count, sizeof(*e->heights)); e->count = p->count; - e->left_spacing = p->left_spacing; - e->right_spacing = p->right_spacing; + e->vertical = p->vertical; + e->pre_spacing = p->pre_spacing; + e->post_spacing = p->post_spacing; for (size_t i = 0; i < p->count; i++) { const struct particle *pp = p->particles[i]; @@ -158,13 +190,14 @@ particle_destroy(struct particle *particle) struct particle * particle_list_new(struct particle *common, struct particle *particles[], size_t count, - int left_spacing, int right_spacing) + bool vertical, int pre_spacing, int post_spacing) { struct private *p = calloc(1, sizeof(*p)); p->particles = malloc(count * sizeof(p->particles[0])); p->count = count; - p->left_spacing = left_spacing; - p->right_spacing = right_spacing; + p->vertical = vertical; + p->pre_spacing = pre_spacing; + p->post_spacing = post_spacing; for (size_t i = 0; i < count; i++) p->particles[i] = particles[i]; @@ -180,13 +213,16 @@ from_conf(const struct yml_node *node, struct particle *common) { const struct yml_node *items = yml_get_value(node, "items"); const struct yml_node *spacing = yml_get_value(node, "spacing"); - const struct yml_node *_left_spacing = yml_get_value(node, "left-spacing"); - const struct yml_node *_right_spacing = yml_get_value(node, "right-spacing"); + const struct yml_node *_pre_spacing = yml_get_value(node, "pre-spacing"); + const struct yml_node *_post_spacing = yml_get_value(node, "post-spacing"); + const struct yml_node *_vertical = yml_get_value(node, "vertical"); - int left_spacing = spacing != NULL ? yml_value_as_int(spacing) : - _left_spacing != NULL ? yml_value_as_int(_left_spacing) : 0; - int right_spacing = spacing != NULL ? yml_value_as_int(spacing) : - _right_spacing != NULL ? yml_value_as_int(_right_spacing) : 2; + int pre_spacing = spacing != NULL ? yml_value_as_int(spacing) : + _pre_spacing != NULL ? yml_value_as_int(_pre_spacing) : 0; + int post_spacing = spacing != NULL ? yml_value_as_int(spacing) : + _post_spacing != NULL ? yml_value_as_int(_post_spacing) : 2; + + bool vertical = _vertical != NULL ? yml_value_as_bool(_vertical) : false; size_t count = yml_list_length(items); struct particle *parts[count]; @@ -200,7 +236,7 @@ from_conf(const struct yml_node *node, struct particle *common) it.node, (struct conf_inherit){common->font, common->font_shaping, common->foreground}); } - return particle_list_new(common, parts, count, left_spacing, right_spacing); + return particle_list_new(common, parts, count, vertical, pre_spacing, post_spacing); } static bool diff --git a/particles/map.c b/particles/map.c index 82a1ee0..53fc1dd 100644 --- a/particles/map.c +++ b/particles/map.c @@ -2,6 +2,7 @@ #include #include #include +#include #define LOG_MODULE "map" #include "../log.h" @@ -184,13 +185,20 @@ begin_expose(struct exposable *exposable) { struct eprivate *e = exposable->private; - int width = e->exposable->begin_expose(e->exposable); - assert(width >= 0); + e->exposable->begin_expose(e->exposable); + + int width = e->exposable->width; + int height = e->exposable->height; + assert(width >= 0 && height >= 0); if (width > 0) width += exposable->particle->left_margin + exposable->particle->right_margin; + if (height > 0) + height += exposable->particle->top_margin + exposable->particle->bottom_margin; exposable->width = width; + exposable->height = height; + return exposable->width; } @@ -199,7 +207,7 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int { struct eprivate *e = exposable->private; - exposable_render_deco(exposable, pix, x, y, height); + exposable_render_deco(exposable, pix, x, y); e->exposable->expose( e->exposable, pix, x + exposable->particle->left_margin, y, height); } @@ -254,7 +262,7 @@ instantiate(const struct particle *particle, const struct tag_set *tags) else if (p->default_particle != NULL) e->exposable = p->default_particle->instantiate(p->default_particle, tags); else - e->exposable = dynlist_exposable_new(NULL, 0, 0, 0); + e->exposable = dynlist_exposable_new(NULL, 0, false, 0, 0); assert(e->exposable != NULL); diff --git a/particles/progress-bar.c b/particles/progress-bar.c index f9e3999..65e7ac5 100644 --- a/particles/progress-bar.c +++ b/particles/progress-bar.c @@ -87,7 +87,7 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int { const struct eprivate *e = exposable->private; - exposable_render_deco(exposable, pix, x, y, height); + exposable_render_deco(exposable, pix, x, y); x += exposable->particle->left_margin; for (size_t i = 0; i < e->count; i++) { diff --git a/particles/ramp.c b/particles/ramp.c index 0127519..2dc5205 100644 --- a/particles/ramp.c +++ b/particles/ramp.c @@ -41,13 +41,19 @@ begin_expose(struct exposable *exposable) { struct eprivate *e = exposable->private; - int width = e->exposable->begin_expose(e->exposable); + e->exposable->begin_expose(e->exposable); + int width = e->exposable->width; + int height = e->exposable->height; assert(width >= 0); if (width > 0) width += exposable->particle->left_margin + exposable->particle->right_margin; + if (height > 0) + height += exposable->particle->top_margin + exposable->particle->bottom_margin; exposable->width = width; + exposable->height = height; + return exposable->width; } @@ -56,7 +62,7 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int { struct eprivate *e = exposable->private; - exposable_render_deco(exposable, pix, x, y, height); + exposable_render_deco(exposable, pix, x, y); e->exposable->expose( e->exposable, pix, x + exposable->particle->left_margin, y, height); } diff --git a/particles/string.c b/particles/string.c index e11ec45..26b8dea 100644 --- a/particles/string.c +++ b/particles/string.c @@ -15,6 +15,7 @@ struct text_run_cache { uint64_t hash; struct fcft_text_run *run; int width; + int height; bool in_use; }; @@ -31,6 +32,7 @@ struct eprivate { const struct fcft_glyph **glyphs; const struct fcft_glyph **allocated_glyphs; long *kern_x; + long *kern_y; int num_glyphs; }; @@ -41,6 +43,7 @@ exposable_destroy(struct exposable *exposable) free(e->allocated_glyphs); free(e->kern_x); + free(e->kern_y); free(e); exposable_default_destroy(exposable); } @@ -50,26 +53,32 @@ begin_expose(struct exposable *exposable) { struct eprivate *e = exposable->private; struct private *p = exposable->particle->private; + const struct fcft_font *font = exposable->particle->font; exposable->width = exposable->particle->left_margin + exposable->particle->right_margin; - + exposable->height = + exposable->particle->top_margin + + exposable->particle->bottom_margin; + exposable->height += font->ascent + font->descent; + if (e->cache_idx >= 0) { exposable->width += p->cache[e->cache_idx].width; } else { /* Calculate the size we need to render the glyphs */ - for (int i = 0; i < e->num_glyphs; i++) + for (int i = 0; i < e->num_glyphs; i++) { exposable->width += e->kern_x[i] + e->glyphs[i]->advance.x; + } } - + LOG_INFO("String height: %d", exposable->height); return exposable->width; } static void expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int height) { - exposable_render_deco(exposable, pix, x, y, height); + exposable_render_deco(exposable, pix, x, y); const struct eprivate *e = exposable->private; const struct fcft_font *font = exposable->particle->font; @@ -97,8 +106,9 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int * any real facts, but works very well with e.g. the "Awesome 6" * font family. */ + // TODO: FIX THIS const double baseline = (double)y + - (double)(height + font->ascent + font->descent) / 2.0 - + (double)(exposable->height + font->ascent + font->descent) / 2.0 - (font->descent > 0 ? font->descent : 0); x += exposable->particle->left_margin; @@ -109,6 +119,7 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int assert(glyph != NULL); x += e->kern_x[i]; + y += e->kern_y[i]; if (pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8) { /* Glyph surface is a pre-rendered image (typically a color emoji...) */ @@ -156,6 +167,7 @@ instantiate(const struct particle *particle, const struct tag_set *tags) e->glyphs = e->allocated_glyphs = NULL; e->num_glyphs = 0; e->kern_x = NULL; + e->kern_y = NULL; e->cache_idx = -1; uint64_t hash = sdbm_hash(text); @@ -170,6 +182,7 @@ instantiate(const struct particle *particle, const struct tag_set *tags) e->glyphs = p->cache[i].run->glyphs; e->num_glyphs = p->cache[i].run->count; e->kern_x = calloc(p->cache[i].run->count, sizeof(e->kern_x[0])); + e->kern_y = calloc(p->cache[i].run->count, sizeof(e->kern_y[0])); goto done; } } @@ -197,6 +210,7 @@ instantiate(const struct particle *particle, const struct tag_set *tags) } e->kern_x = calloc(chars, sizeof(e->kern_x[0])); + e->kern_y = calloc(chars, sizeof(e->kern_y[0])); if (particle->font_shaping == FONT_SHAPE_FULL && fcft_capabilities() & FCFT_CAPABILITY_TEXT_RUN_SHAPING) @@ -205,9 +219,11 @@ instantiate(const struct particle *particle, const struct tag_set *tags) font, chars, wtext, FCFT_SUBPIXEL_NONE); if (run != NULL) { - int w = 0; - for (size_t i = 0; i < run->count; i++) + int w = 0, h = 0; + for (size_t i = 0; i < run->count; i++) { w += run->glyphs[i]->advance.x; + h += run->glyphs[i]->advance.y; + } ssize_t cache_idx = -1; for (size_t i = 0; i < p->cache_size; i++) { @@ -232,6 +248,7 @@ instantiate(const struct particle *particle, const struct tag_set *tags) p->cache[cache_idx].hash = hash; p->cache[cache_idx].run = run; p->cache[cache_idx].width = w; + p->cache[cache_idx].height = h; p->cache[cache_idx].in_use = true; e->cache_idx = cache_idx; @@ -256,7 +273,7 @@ instantiate(const struct particle *particle, const struct tag_set *tags) if (i == 0) continue; - fcft_kerning(font, wtext[i - 1], wtext[i], &e->kern_x[i], NULL); + fcft_kerning(font, wtext[i - 1], wtext[i], &e->kern_x[i], &e->kern_y[i]); } e->glyphs = e->allocated_glyphs;