diff --git a/bar/bar.c b/bar/bar.c index 10e0785..c87ffc7 100644 --- a/bar/bar.c +++ b/bar/bar.c @@ -28,33 +28,68 @@ #define max(x, y) ((x) > (y) ? (x) : (y)) /* - * Calculate total width of left/center/rigth groups. + * Repeat a given action for all widths in a section + * and store the result in out. + * + * Note: out should first be set to zero or the action will + * also be preformed on the pre-given value. + */ +static void +accum_widths(const struct section *s, const struct private *b, + int *out, int (*act)(int a, int b)) +{ + for (size_t i = 0; i < s->count; i++) { + struct exposable *e = s->exps[i]; + if (e->height > 0) + *out = act(*out, b->left_spacing + e->width + b->right_spacing); + } +} + +/* + * Repeat a given action for all heights in a section + * and store the result in out. + * + * Note: out should first be set to zero or the action will + * also be preformed on the pre-given value. + */ +static void +accum_heights(const struct section *s, const struct private *b, + int *out, int (*act)(int a, int b)) +{ + for (size_t i = 0; i < s->count; i++) { + struct exposable *e = s->exps[i]; + if (e->height > 0) + *out = act(*out, b->top_spacing + e->height + b->bottom_spacing); + } +} + + +/* Add action */ +static int +add (int a, int b) +{ + return a + b; +} + + +/* Max action */ +static int +larger(int a, int b) +{ + return max(a, b); +} + +/* + * Calculate total width of left/center/right groups. * Note: begin_expose() must have been called */ static void calculate_widths(const struct private *b, int *left, int *center, int *right) { - *left = 0; - *center = 0; - *right = 0; - - for (size_t i = 0; i < b->left.count; i++) { - struct exposable *e = b->left.exps[i]; - if (e->width > 0) - *left += b->left_spacing + e->width + b->right_spacing; - } - - for (size_t i = 0; i < b->center.count; i++) { - struct exposable *e = b->center.exps[i]; - if (e->width > 0) - *center += b->left_spacing + e->width + b->right_spacing; - } - - for (size_t i = 0; i < b->right.count; i++) { - struct exposable *e = b->right.exps[i]; - if (e->width > 0) - *right += b->left_spacing + e->width + b->right_spacing; - } + *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); /* No spacing on the edges (that's what the margins are for) */ if (*left > 0) @@ -69,6 +104,68 @@ calculate_widths(const struct private *b, int *left, int *center, int *right) assert(*right >= 0); } +/* + * Calculate total height of left/center/right groups. + * Note: begin_expose() must have been called + */ +static void +calculate_heights (const struct private *b, int *top, int *middle, int *bottom) +{ + *top = 0; + *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); + + /* No spacing on the edges (that's what the margins are for) */ + if (*top > 0) + *top -= b->top_spacing + b->bottom_spacing; + if (*middle > 0) + *middle -= b->top_spacing + b->bottom_spacing; + if (*bottom > 0) + *bottom -= b->top_spacing + b->bottom_spacing; + + assert(*top >= 0); + assert(*middle >= 0); + assert(*bottom >= 0); +} + +/* + * 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. + * NOTE: begin_expose() must have been called + */ +static int +min_bar_width (const struct private *b) +{ + int max = 0; + + accum_widths(&(b->left), b, &max, &larger); + accum_widths(&(b->center), b, &max, &larger); + accum_widths(&(b->right), b, &max, &larger); + + return max; +} + +/* + * Calculate the minimum height the bar needs to be to show all particles. + * This assumes the bar is at the top or bottom of the screen. + * NOTE: begin_expose() must have been called + */ +static int +min_bar_height (const struct private *b) +{ + int max = 0; + + accum_heights(&(b->left), b, &max, &larger); + accum_heights(&(b->center), b, &max, &larger); + accum_heights(&(b->right), b, &max, &larger); + + return max; +} + static void expose(const struct bar *_bar) { @@ -77,7 +174,7 @@ expose(const struct bar *_bar) pixman_image_fill_rectangles( PIXMAN_OP_SRC, pix, &bar->background, 1, - &(pixman_rectangle16_t){0, 0, bar->width, bar->height_with_border}); + &(pixman_rectangle16_t){0, 0, bar->width_with_border, bar->height_with_border}); pixman_image_fill_rectangles( PIXMAN_OP_OVER, pix, &bar->border.color, 4, @@ -86,19 +183,19 @@ expose(const struct bar *_bar) {0, 0, bar->border.left_width, bar->height_with_border}, /* Right */ - {bar->width - bar->border.right_width, + {bar->width_with_border - bar->border.right_width, 0, bar->border.right_width, bar->height_with_border}, /* Top */ {bar->border.left_width, 0, - bar->width - bar->border.left_width - bar->border.right_width, + bar->width_with_border - bar->border.left_width - bar->border.right_width, bar->border.top_width}, /* Bottom */ {bar->border.left_width, bar->height_with_border - bar->border.bottom_width, - bar->width - bar->border.left_width - bar->border.right_width, + bar->width_with_border - bar->border.left_width - bar->border.right_width, bar->border.bottom_width}, }); @@ -296,6 +393,9 @@ run(struct bar *_bar) bar->height_with_border = bar->height + bar->border.top_width + bar->border.bottom_width; + + bar->width_with_border = + bar->width + bar->border.left_width + bar->border.right_width; if (!bar->backend.iface->setup(_bar)) { bar->backend.iface->cleanup(_bar); @@ -473,11 +573,16 @@ bar_new(const struct bar_config *config) priv->layer = config->layer; priv->location = config->location; priv->height = config->height; + priv->width = config->width; priv->background = config->background; priv->left_spacing = config->left_spacing; priv->right_spacing = config->right_spacing; priv->left_margin = config->left_margin; priv->right_margin = config->right_margin; + priv->top_spacing = config->top_spacing; + priv->bottom_spacing = config->bottom_spacing; + priv->top_margin = config->top_margin; + priv->bottom_margin = config->bottom_margin; priv->trackpad_sensitivity = config->trackpad_sensitivity; priv->border.left_width = config->border.left_width; priv->border.right_width = config->border.right_width; diff --git a/bar/bar.h b/bar/bar.h index 717b690..7ff4e46 100644 --- a/bar/bar.h +++ b/bar/bar.h @@ -17,7 +17,7 @@ struct bar { const char *(*output_name)(const struct bar *bar); }; -enum bar_location { BAR_TOP, BAR_BOTTOM }; +enum bar_location { BAR_TOP, BAR_BOTTOM, BAR_LEFT, BAR_RIGHT }; enum bar_layer { BAR_LAYER_TOP, BAR_LAYER_BOTTOM }; enum bar_backend { BAR_BACKEND_AUTO, BAR_BACKEND_XCB, BAR_BACKEND_WAYLAND }; @@ -31,6 +31,9 @@ struct bar_config { int height; int left_spacing, right_spacing; int left_margin, right_margin; + int width; + int top_spacing, bottom_spacing; + int top_margin, bottom_margin; int trackpad_sensitivity; pixman_color_t background; diff --git a/bar/private.h b/bar/private.h index f216c99..6bd9f20 100644 --- a/bar/private.h +++ b/bar/private.h @@ -3,6 +3,12 @@ #include "../bar/bar.h" #include "backend.h" +struct section { + struct module **mods; + struct exposable **exps; + size_t count; +}; + struct private { /* From bar_config */ char *monitor; @@ -11,6 +17,9 @@ struct private { int height; int left_spacing, right_spacing; int left_margin, right_margin; + int width; + int top_spacing, bottom_spacing; + int top_margin, bottom_margin; int trackpad_sensitivity; pixman_color_t background; @@ -23,25 +32,13 @@ struct private { int top_margin, bottom_margin; } border; - struct { - struct module **mods; - struct exposable **exps; - size_t count; - } left; - struct { - struct module **mods; - struct exposable **exps; - size_t count; - } center; - struct { - struct module **mods; - struct exposable **exps; - size_t count; - } right; + struct section left; + struct section center; + struct section right; /* Calculated run-time */ - int width; int height_with_border; + int width_with_border; pixman_image_t *pix; diff --git a/bar/wayland.c b/bar/wayland.c index edbf0db..2bc89cf 100644 --- a/bar/wayland.c +++ b/bar/wayland.c @@ -824,16 +824,24 @@ create_surface(struct wayland_backend *backend) zwlr_layer_surface_v1_add_listener( backend->layer_surface, &layer_surface_listener, backend); - /* Aligned to top, maximum width */ - enum zwlr_layer_surface_v1_anchor top_or_bottom = bar->location == BAR_TOP - ? ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP - : ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; + enum zwlr_layer_surface_v1_anchor full_anchor = + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + + if (bar->location & BAR_TOP) + full_anchor ^= ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; + if (bar->location & BAR_BOTTOM) + full_anchor ^= ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP; + if (bar->location & BAR_LEFT) + full_anchor ^= ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + if (bar->location & BAR_RIGHT) + full_anchor ^= ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT; zwlr_layer_surface_v1_set_anchor( - backend->layer_surface, - ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | - ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | - top_or_bottom); + backend->layer_surface, + full_anchor); return true; } @@ -1036,20 +1044,29 @@ update_size(struct wayland_backend *backend) backend->scale = scale; - int height = bar->height_with_border; - height /= scale; - height *= scale; + int height = bar->height; bar->height = height - bar->border.top_width - bar->border.bottom_width; bar->height_with_border = height; - zwlr_layer_surface_v1_set_size( - backend->layer_surface, 0, bar->height_with_border / scale); - zwlr_layer_surface_v1_set_exclusive_zone( - backend->layer_surface, - (bar->height_with_border + (bar->location == BAR_TOP - ? bar->border.bottom_margin - : bar->border.top_margin)) - / scale); + if (bar->location == BAR_TOP || bar->location == BAR_BOTTOM) { + zwlr_layer_surface_v1_set_size( + backend->layer_surface, 0, bar->height_with_border / scale); + zwlr_layer_surface_v1_set_exclusive_zone( + backend->layer_surface, + (bar->height_with_border + (bar->location == BAR_TOP + ? bar->border.bottom_margin + : bar->border.top_margin)) + / scale); + } else { + zwlr_layer_surface_v1_set_size( + backend->layer_surface, bar->width_with_border / scale, 0); + zwlr_layer_surface_v1_set_exclusive_zone( + backend->layer_surface, + (bar->width_with_border + (bar->location == BAR_LEFT + ? bar->border.right_margin + : bar->border.left_margin)) + / scale); + } zwlr_layer_surface_v1_set_margin( backend->layer_surface, @@ -1063,13 +1080,13 @@ update_size(struct wayland_backend *backend) wl_surface_commit(backend->surface); wl_display_roundtrip(backend->display); - if (backend->width == -1 || - backend->height != bar->height_with_border) { - LOG_ERR("failed to get panel width"); + if (backend->width == -1 || backend->height == -1) { + LOG_ERR("failed to get panel size"); return false; } bar->width = backend->width; + bar->height = backend->height; /* Reload buffers */ if (backend->next_buffer != NULL) diff --git a/config.c b/config.c index 3d32678..35a27c5 100644 --- a/config.c +++ b/config.c @@ -290,9 +290,6 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend) * Required attributes */ - const struct yml_node *height = yml_get_value(bar, "height"); - conf.height = yml_value_as_int(height); - const struct yml_node *location = yml_get_value(bar, "location"); conf.location = strcmp(yml_value_as_string(location), "top") == 0 ? BAR_TOP : BAR_BOTTOM; @@ -304,6 +301,18 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend) * Optional attributes */ + const struct yml_node *height = yml_get_value(bar, "height"); + if (height != NULL) + conf.height = yml_value_as_int(height); + else + conf.height = -1; // Represents 'auto' height + + const struct yml_node *width = yml_get_value(bar, "width"); + if (width != NULL) + conf.width = yml_value_as_int(height); + else + conf.width = -1; // Represents 'auto' width + const struct yml_node *monitor = yml_get_value(bar, "monitor"); if (monitor != NULL) conf.monitor = yml_value_as_string(monitor); @@ -322,6 +331,7 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend) const struct yml_node *spacing = yml_get_value(bar, "spacing"); if (spacing != NULL) + conf.top_spacing = conf.bottom_spacing = conf.left_spacing = conf.right_spacing = yml_value_as_int(spacing); const struct yml_node *left_spacing = yml_get_value(bar, "left-spacing"); @@ -331,9 +341,18 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend) const struct yml_node *right_spacing = yml_get_value(bar, "right-spacing"); if (right_spacing != NULL) conf.right_spacing = yml_value_as_int(right_spacing); + + const struct yml_node *top_spacing = yml_get_value(bar, "top-spacing"); + if (top_spacing != NULL) + conf.left_spacing = yml_value_as_int(top_spacing); + + const struct yml_node *bottom_spacing = yml_get_value(bar, "bottom-spacing"); + if (bottom_spacing != NULL) + conf.bottom_spacing = yml_value_as_int(bottom_spacing); const struct yml_node *margin = yml_get_value(bar, "margin"); if (margin != NULL) + conf.top_margin = conf.bottom_margin = conf.left_margin = conf.right_margin = yml_value_as_int(margin); const struct yml_node *left_margin = yml_get_value(bar, "left-margin"); @@ -343,6 +362,14 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend) const struct yml_node *right_margin = yml_get_value(bar, "right-margin"); if (right_margin != NULL) conf.right_margin = yml_value_as_int(right_margin); + + const struct yml_node *top_margin = yml_get_value(bar, "top-margin"); + if (top_margin != NULL) + conf.left_margin = yml_value_as_int(top_margin); + + const struct yml_node *bottom_margin = yml_get_value(bar, "bottom-margin"); + if (bottom_margin != NULL) + conf.bottom_margin = yml_value_as_int(bottom_margin); const struct yml_node *trackpad_sensitivity = yml_get_value(bar, "trackpad-sensitivity"); diff --git a/particle.h b/particle.h index c92c5fc..92ae9ad 100644 --- a/particle.h +++ b/particle.h @@ -52,6 +52,8 @@ struct exposable { void *private; int width; /* Should be set by begin_expose(), at latest */ + int height; + char *on_click[MOUSE_BTN_COUNT]; void (*destroy)(struct exposable *exposable);