aboutsummaryrefslogtreecommitdiff
path: root/swaybar/render.c
diff options
context:
space:
mode:
Diffstat (limited to 'swaybar/render.c')
-rw-r--r--swaybar/render.c638
1 files changed, 397 insertions, 241 deletions
diff --git a/swaybar/render.c b/swaybar/render.c
index 6fc09078..26248d35 100644
--- a/swaybar/render.c
+++ b/swaybar/render.c
@@ -1,35 +1,92 @@
+#define _POSIX_C_SOURCE 200809L
+#include <limits.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
-
-#include "client/cairo.h"
-#include "client/pango.h"
-#include "client/window.h"
+#include <wlr/util/log.h>
+#include "cairo.h"
+#include "pango.h"
+#include "pool-buffer.h"
+#include "swaybar/bar.h"
#include "swaybar/config.h"
-#include "swaybar/status_line.h"
+#include "swaybar/ipc.h"
#include "swaybar/render.h"
-#ifdef ENABLE_TRAY
-#include "swaybar/tray/tray.h"
-#include "swaybar/tray/sni.h"
-#endif
-#include "log.h"
-
-
-/* internal spacing */
-static int margin = 3;
-static int ws_horizontal_padding = 5;
-static double ws_vertical_padding = 1.5;
-static int ws_spacing = 1;
-
-/**
- * Renders a sharp line of any width and height.
- *
- * The line is drawn from (x,y) to (x+width,y+height) where width/height is 0
- * if the line has a width/height of one pixel, respectively.
- */
-static void render_sharp_line(cairo_t *cairo, uint32_t color, double x, double y, double width, double height) {
- cairo_set_source_u32(cairo, color);
+#include "swaybar/status_line.h"
+#include "wlr-layer-shell-unstable-v1-client-protocol.h"
+
+static const int WS_HORIZONTAL_PADDING = 5;
+static const double WS_VERTICAL_PADDING = 1.5;
+static const double BORDER_WIDTH = 1;
+
+static uint32_t render_status_line_error(cairo_t *cairo,
+ struct swaybar_output *output, struct swaybar_config *config,
+ const char *error, double *x, uint32_t surface_height) {
+ if (!error) {
+ return 0;
+ }
+
+ uint32_t height = surface_height * output->scale;
+
+ cairo_set_source_u32(cairo, 0xFF0000FF);
+
+ int margin = 3 * output->scale;
+ int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale;
+
+ int text_width, text_height;
+ get_text_size(cairo, config->font,
+ &text_width, &text_height, output->scale, false, "%s", error);
+
+ uint32_t ideal_height = text_height + ws_vertical_padding * 2;
+ uint32_t ideal_surface_height = ideal_height / output->scale;
+ if (surface_height < ideal_surface_height) {
+ return ideal_surface_height;
+ }
+ *x -= text_width + margin;
+
+ double text_y = height / 2.0 - text_height / 2.0;
+ cairo_move_to(cairo, *x, (int)floor(text_y));
+ pango_printf(cairo, config->font, output->scale, false, "%s", error);
+ *x -= margin;
+ return surface_height;
+}
+
+static uint32_t render_status_line_text(cairo_t *cairo,
+ struct swaybar_output *output, struct swaybar_config *config,
+ const char *text, bool focused, double *x, uint32_t surface_height) {
+ if (!text) {
+ return 0;
+ }
+
+ uint32_t height = surface_height * output->scale;
+
+ cairo_set_source_u32(cairo, focused ?
+ config->colors.focused_statusline : config->colors.statusline);
+ int text_width, text_height;
+ get_text_size(cairo, config->font, &text_width, &text_height,
+ output->scale, config->pango_markup, "%s", text);
+
+ int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale;
+ int margin = 3 * output->scale;
+
+ uint32_t ideal_height = text_height + ws_vertical_padding * 2;
+ uint32_t ideal_surface_height = ideal_height / output->scale;
+ if (surface_height < ideal_surface_height) {
+ return ideal_surface_height;
+ }
+
+ *x -= text_width + margin;
+ double text_y = height / 2.0 - text_height / 2.0;
+ cairo_move_to(cairo, *x, (int)floor(text_y));
+ pango_printf(cairo, config->font, output->scale,
+ config->pango_markup, "%s", text);
+ *x -= margin;
+ return surface_height;
+}
+
+static void render_sharp_line(cairo_t *cairo, uint32_t color,
+ double x, double y, double width, double height) {
+ cairo_set_source_u32(cairo, color);
if (width > 1 && height > 1) {
cairo_rectangle(cairo, x, y, width, height);
cairo_fill(cairo);
@@ -39,13 +96,11 @@ static void render_sharp_line(cairo_t *cairo, uint32_t color, double x, double y
height += y;
width = x;
}
-
if (height == 1) {
y += 0.5;
width += x;
height = y;
}
-
cairo_move_to(cairo, x, y);
cairo_set_line_width(cairo, 1.0);
cairo_line_to(cairo, width, height);
@@ -53,176 +108,256 @@ static void render_sharp_line(cairo_t *cairo, uint32_t color, double x, double y
}
}
-static void render_block(struct window *window, struct config *config, struct status_block *block, double *x, bool edge, bool is_focused) {
- int width, height, sep_width;
- get_text_size(window->cairo, window->font, &width, &height,
- window->scale, block->markup, "%s", block->full_text);
+static void block_hotspot_callback(struct swaybar_output *output,
+ int x, int y, uint32_t button, void *data) {
+ struct i3bar_block *block = data;
+ struct status_line *status = output->bar->status;
+ i3bar_block_send_click(status, block, x, y, button);
+}
- int textwidth = width;
- double block_width = width;
+static uint32_t render_status_block(cairo_t *cairo,
+ struct swaybar_config *config, struct swaybar_output *output,
+ struct i3bar_block *block, double *x,
+ uint32_t surface_height, bool focused, bool edge) {
+ if (!block->full_text || !*block->full_text) {
+ return 0;
+ }
+ uint32_t height = surface_height * output->scale;
+
+ int text_width, text_height;
+ get_text_size(cairo, config->font, &text_width, &text_height,
+ output->scale, block->markup, "%s", block->full_text);
+
+ int margin = 3 * output->scale;
+ int ws_vertical_padding = WS_VERTICAL_PADDING * 2;
+
+ int width = text_width;
if (width < block->min_width) {
width = block->min_width;
}
- *x -= width;
+ double block_width = width;
+ uint32_t ideal_height = text_height + ws_vertical_padding * 2;
+ uint32_t ideal_surface_height = ideal_height / output->scale;
+ if (surface_height < ideal_surface_height) {
+ return ideal_surface_height;
+ }
- if (block->border != 0 && block->border_left > 0) {
+ *x -= width;
+ if (block->border && block->border_left > 0) {
*x -= (block->border_left + margin);
block_width += block->border_left + margin;
}
-
- if (block->border != 0 && block->border_right > 0) {
+ if (block->border && block->border_right > 0) {
*x -= (block->border_right + margin);
block_width += block->border_right + margin;
}
- // Add separator
+ int sep_width, sep_height;
if (!edge) {
if (config->sep_symbol) {
- get_text_size(window->cairo, window->font, &sep_width, &height,
- window->scale, false, "%s", config->sep_symbol);
+ get_text_size(cairo, config->font, &sep_width, &sep_height,
+ output->scale, false, "%s", config->sep_symbol);
+ uint32_t _ideal_height = sep_height + ws_vertical_padding * 2;
+ uint32_t _ideal_surface_height = _ideal_height / output->scale;
+ if (surface_height < _ideal_surface_height) {
+ return _ideal_surface_height;
+ }
if (sep_width > block->separator_block_width) {
block->separator_block_width = sep_width + margin * 2;
}
}
-
*x -= block->separator_block_width;
} else {
*x -= margin;
}
- double pos = *x;
-
- block->x = (int)pos;
- block->width = (int)block_width;
+ struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot));
+ hotspot->x = *x;
+ hotspot->y = 0;
+ hotspot->width = width;
+ hotspot->height = height;
+ hotspot->callback = block_hotspot_callback;
+ hotspot->destroy = NULL;
+ hotspot->data = block;
+ wl_list_insert(&output->hotspots, &hotspot->link);
- // render background
- if (block->background != 0x0) {
- cairo_set_source_u32(window->cairo, block->background);
- cairo_rectangle(window->cairo, pos - 0.5, 1, block_width, (window->height * window->scale) - 2);
- cairo_fill(window->cairo);
+ double pos = *x;
+ if (block->background) {
+ cairo_set_source_u32(cairo, block->background);
+ cairo_rectangle(cairo, pos - 0.5 * output->scale,
+ output->scale, block_width, height);
+ cairo_fill(cairo);
}
- // render top border
- if (block->border != 0 && block->border_top > 0) {
- render_sharp_line(window->cairo, block->border,
- pos - 0.5,
- 1,
- block_width,
- block->border_top);
+ if (block->border && block->border_top > 0) {
+ render_sharp_line(cairo, block->border,
+ pos - 0.5 * output->scale, output->scale,
+ block_width, block->border_top);
}
-
- // render bottom border
- if (block->border != 0 && block->border_bottom > 0) {
- render_sharp_line(window->cairo, block->border,
- pos - 0.5,
- (window->height * window->scale) - 1 - block->border_bottom,
- block_width,
- block->border_bottom);
+ if (block->border && block->border_bottom > 0) {
+ render_sharp_line(cairo, block->border,
+ pos - 0.5 * output->scale,
+ height - output->scale - block->border_bottom,
+ block_width, block->border_bottom);
}
-
- // render left border
if (block->border != 0 && block->border_left > 0) {
- render_sharp_line(window->cairo, block->border,
- pos - 0.5,
- 1,
- block->border_left,
- (window->height * window->scale) - 2);
-
+ render_sharp_line(cairo, block->border,
+ pos - 0.5 * output->scale, output->scale,
+ block->border_left, height);
pos += block->border_left + margin;
}
- // render text
double offset = 0;
-
if (strncmp(block->align, "left", 5) == 0) {
offset = pos;
} else if (strncmp(block->align, "right", 5) == 0) {
- offset = pos + width - textwidth;
+ offset = pos + width - text_width;
} else if (strncmp(block->align, "center", 6) == 0) {
- offset = pos + (width - textwidth) / 2;
+ offset = pos + (width - text_width) / 2;
}
-
- cairo_move_to(window->cairo, offset, margin);
- cairo_set_source_u32(window->cairo, block->color);
- pango_printf(window->cairo, window->font, window->scale,
+ cairo_move_to(cairo, offset, height / 2.0 - text_height / 2.0);
+ uint32_t color = block->color ? *block->color : config->colors.statusline;
+ cairo_set_source_u32(cairo, color);
+ pango_printf(cairo, config->font, output->scale,
block->markup, "%s", block->full_text);
-
pos += width;
- // render right border
- if (block->border != 0 && block->border_right > 0) {
+ if (block->border && block->border_right > 0) {
pos += margin;
-
- render_sharp_line(window->cairo, block->border,
- pos - 0.5,
- 1,
- block->border_right,
- (window->height * window->scale) - 2);
-
+ render_sharp_line(cairo, block->border,
+ pos - 0.5 * output->scale, output->scale,
+ block->border_right, height);
pos += block->border_right;
}
- // render separator
if (!edge && block->separator) {
- if (is_focused) {
- cairo_set_source_u32(window->cairo, config->colors.focused_separator);
+ if (focused) {
+ cairo_set_source_u32(cairo, config->colors.focused_separator);
} else {
- cairo_set_source_u32(window->cairo, config->colors.separator);
+ cairo_set_source_u32(cairo, config->colors.separator);
}
if (config->sep_symbol) {
offset = pos + (block->separator_block_width - sep_width) / 2;
- cairo_move_to(window->cairo, offset, margin);
- pango_printf(window->cairo, window->font, window->scale,
- false, "%s", config->sep_symbol);
+ cairo_move_to(cairo, offset, height / 2.0 - sep_height / 2.0);
+ pango_printf(cairo, config->font, output->scale, false,
+ "%s", config->sep_symbol);
} else {
- cairo_set_line_width(window->cairo, 1);
- cairo_move_to(window->cairo, pos + block->separator_block_width/2,
- margin);
- cairo_line_to(window->cairo, pos + block->separator_block_width/2,
- (window->height * window->scale) - margin);
- cairo_stroke(window->cairo);
+ cairo_set_line_width(cairo, 1);
+ cairo_move_to(cairo,
+ pos + block->separator_block_width / 2, margin);
+ cairo_line_to(cairo,
+ pos + block->separator_block_width / 2, height - margin);
+ cairo_stroke(cairo);
}
}
+ return surface_height;
+}
+static uint32_t render_status_line_i3bar(cairo_t *cairo,
+ struct swaybar_config *config, struct swaybar_output *output,
+ struct status_line *status, bool focused,
+ double *x, uint32_t surface_height) {
+ uint32_t max_height = 0;
+ bool edge = true;
+ struct i3bar_block *block;
+ wl_list_for_each(block, &status->blocks, link) {
+ uint32_t h = render_status_block(cairo, config, output,
+ block, x, surface_height, focused, edge);
+ max_height = h > max_height ? h : max_height;
+ edge = false;
+ }
+ return max_height;
}
-static const char *strip_workspace_name(bool strip_num, const char *ws_name) {
- bool strip = false;
- int i;
-
- if (strip_num) {
- int len = strlen(ws_name);
- for (i = 0; i < len; ++i) {
- if (!('0' <= ws_name[i] && ws_name[i] <= '9')) {
- if (':' == ws_name[i] && i < len-1 && i > 0) {
- strip = true;
- ++i;
- }
- break;
- }
- }
+static uint32_t render_status_line(cairo_t *cairo,
+ struct swaybar_config *config, struct swaybar_output *output,
+ struct status_line *status, bool focused,
+ double *x, uint32_t surface_height) {
+ switch (status->protocol) {
+ case PROTOCOL_ERROR:
+ return render_status_line_error(cairo, output, config,
+ status->text, x, surface_height);
+ case PROTOCOL_TEXT:
+ return render_status_line_text(cairo, output, config,
+ status->text, focused, x, surface_height);
+ case PROTOCOL_I3BAR:
+ return render_status_line_i3bar(cairo, config, output,
+ status, focused, x, surface_height);
+ case PROTOCOL_UNDEF:
+ return 0;
}
+ return 0;
+}
+
+static uint32_t render_binding_mode_indicator(cairo_t *cairo,
+ struct swaybar_output *output, struct swaybar_config *config,
+ const char *mode, double x, uint32_t surface_height) {
+ uint32_t height = surface_height * output->scale;
- if (strip) {
- return ws_name + i;
+ int text_width, text_height;
+ get_text_size(cairo, config->font, &text_width, &text_height,
+ output->scale, true, "%s", mode);
+
+ int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale;
+ int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale;
+ int border_width = BORDER_WIDTH * output->scale;
+
+ uint32_t ideal_height = text_height + ws_vertical_padding * 2
+ + border_width * 2;
+ uint32_t ideal_surface_height = ideal_height / output->scale;
+ if (surface_height < ideal_surface_height) {
+ return ideal_surface_height;
}
+ uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2;
+
+ cairo_set_source_u32(cairo, config->colors.binding_mode.background);
+ cairo_rectangle(cairo, x, 0, width, height);
+ cairo_fill(cairo);
+
+ cairo_set_source_u32(cairo, config->colors.binding_mode.border);
+ cairo_rectangle(cairo, x, 0, width, border_width);
+ cairo_fill(cairo);
+ cairo_rectangle(cairo, x, 0, border_width, height);
+ cairo_fill(cairo);
+ cairo_rectangle(cairo, x + width - border_width, 0, border_width, height);
+ cairo_fill(cairo);
+ cairo_rectangle(cairo, x, height - border_width, width, border_width);
+ cairo_fill(cairo);
+
+ double text_y = height / 2.0 - text_height / 2.0;
+ cairo_set_source_u32(cairo, config->colors.binding_mode.text);
+ cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y));
+ pango_printf(cairo, config->font, output->scale, true, "%s", mode);
+ return surface_height;
+}
+static const char *strip_workspace_number(const char *ws_name) {
+ size_t len = strlen(ws_name);
+ for (size_t i = 0; i < len; ++i) {
+ if (ws_name[i] < '0' || ws_name[i] > '9') {
+ if (':' == ws_name[i] && i < len - 1 && i > 0) {
+ return ws_name + i + 1;
+ }
+ return ws_name;
+ }
+ }
return ws_name;
}
-void workspace_button_size(struct window *window, const char *workspace_name, int *width, int *height) {
- const char *stripped_name = strip_workspace_name(swaybar.config->strip_workspace_numbers, workspace_name);
-
- get_text_size(window->cairo, window->font, width, height,
- window->scale, true, "%s", stripped_name);
- *width += 2 * ws_horizontal_padding;
- *height += 2 * ws_vertical_padding;
+static void workspace_hotspot_callback(struct swaybar_output *output,
+ int x, int y, uint32_t button, void *data) {
+ ipc_send_workspace_command(output->bar, (const char *)data);
}
-static void render_workspace_button(struct window *window, struct config *config, struct workspace *ws, double *x) {
- const char *stripped_name = strip_workspace_name(config->strip_workspace_numbers, ws->name);
+static uint32_t render_workspace_button(cairo_t *cairo,
+ struct swaybar_output *output, struct swaybar_config *config,
+ struct swaybar_workspace *ws, double *x, uint32_t surface_height) {
+ const char *name = ws->name;
+ if (config->strip_workspace_numbers) {
+ name = strip_workspace_number(ws->name);
+ }
struct box_colors box_colors;
if (ws->urgent) {
@@ -235,133 +370,154 @@ static void render_workspace_button(struct window *window, struct config *config
box_colors = config->colors.inactive_workspace;
}
- int width, height;
- workspace_button_size(window, stripped_name, &width, &height);
+ uint32_t height = surface_height * output->scale;
- // background
- cairo_set_source_u32(window->cairo, box_colors.background);
- cairo_rectangle(window->cairo, *x, 1.5, width - 1, height);
- cairo_fill(window->cairo);
-
- // border
- cairo_set_source_u32(window->cairo, box_colors.border);
- cairo_rectangle(window->cairo, *x, 1.5, width - 1, height);
- cairo_stroke(window->cairo);
-
- // text
- cairo_set_source_u32(window->cairo, box_colors.text);
- cairo_move_to(window->cairo, (int)*x + ws_horizontal_padding, margin);
- pango_printf(window->cairo, window->font, window->scale,
- true, "%s", stripped_name);
-
- *x += width + ws_spacing;
-}
+ int text_width, text_height;
+ get_text_size(cairo, config->font, &text_width, &text_height,
+ output->scale, true, "%s", name);
+
+ int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale;
+ int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale;
+ int border_width = BORDER_WIDTH * output->scale;
+
+ uint32_t ideal_height = ws_vertical_padding * 2 + text_height
+ + border_width * 2;
+ uint32_t ideal_surface_height = ideal_height / output->scale;
+ if (surface_height < ideal_surface_height) {
+ return ideal_surface_height;
+ }
-static void render_binding_mode_indicator(struct window *window, struct config *config, double pos) {
- int width, height;
- get_text_size(window->cairo, window->font, &width, &height,
- window->scale, false, "%s", config->mode);
-
- // background
- cairo_set_source_u32(window->cairo, config->colors.binding_mode.background);
- cairo_rectangle(window->cairo, pos, 1.5, width + ws_horizontal_padding * 2 - 1,
- height + ws_vertical_padding * 2);
- cairo_fill(window->cairo);
-
- // border
- cairo_set_source_u32(window->cairo, config->colors.binding_mode.border);
- cairo_rectangle(window->cairo, pos, 1.5, width + ws_horizontal_padding * 2 - 1,
- height + ws_vertical_padding * 2);
- cairo_stroke(window->cairo);
-
- // text
- cairo_set_source_u32(window->cairo, config->colors.binding_mode.text);
- cairo_move_to(window->cairo, (int)pos + ws_horizontal_padding, margin);
- pango_printf(window->cairo, window->font, window->scale,
- false, "%s", config->mode);
+ uint32_t width = ws_horizontal_padding * 2 + text_width + border_width * 2;
+
+ cairo_set_source_u32(cairo, box_colors.background);
+ cairo_rectangle(cairo, *x, 0, width, height);
+ cairo_fill(cairo);
+
+ cairo_set_source_u32(cairo, box_colors.border);
+ cairo_rectangle(cairo, *x, 0, width, border_width);
+ cairo_fill(cairo);
+ cairo_rectangle(cairo, *x, 0, border_width, height);
+ cairo_fill(cairo);
+ cairo_rectangle(cairo, *x + width - border_width, 0, border_width, height);
+ cairo_fill(cairo);
+ cairo_rectangle(cairo, *x, height - border_width, width, border_width);
+ cairo_fill(cairo);
+
+ double text_y = height / 2.0 - text_height / 2.0;
+ cairo_set_source_u32(cairo, box_colors.text);
+ cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y));
+ pango_printf(cairo, config->font, output->scale, true, "%s", name);
+
+ struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot));
+ hotspot->x = *x;
+ hotspot->y = 0;
+ hotspot->width = width;
+ hotspot->height = height;
+ hotspot->callback = workspace_hotspot_callback;
+ hotspot->destroy = free;
+ hotspot->data = strdup(ws->name);
+ wl_list_insert(&output->hotspots, &hotspot->link);
+
+ *x += width;
+ return surface_height;
}
-void render(struct output *output, struct config *config, struct status_line *line) {
- int i;
-
- struct window *window = output->window;
- cairo_t *cairo = window->cairo;
- bool is_focused = output->focused;
-
- // Clear
- cairo_save(cairo);
- cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR);
- cairo_paint(cairo);
- cairo_restore(cairo);
-
+static uint32_t render_to_cairo(cairo_t *cairo,
+ struct swaybar *bar, struct swaybar_output *output) {
+ struct swaybar_config *config = bar->config;
cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
-
- // Background
- if (is_focused) {
+ if (output->focused) {
cairo_set_source_u32(cairo, config->colors.focused_background);
} else {
cairo_set_source_u32(cairo, config->colors.background);
}
cairo_paint(cairo);
-#ifdef ENABLE_TRAY
- uint32_t tray_width = tray_render(output, config);
-#else
- const uint32_t tray_width = window->width * window->scale;
-#endif
-
- // Command output
- if (is_focused) {
- cairo_set_source_u32(cairo, config->colors.focused_statusline);
- } else {
- cairo_set_source_u32(cairo, config->colors.statusline);
- }
-
- int width, height;
-
- if (line->protocol == TEXT) {
- get_text_size(window->cairo, window->font, &width, &height,
- window->scale, config->pango_markup, "%s", line->text_line);
- cairo_move_to(cairo, tray_width - margin - width, margin);
- pango_printf(window->cairo, window->font, window->scale,
- config->pango_markup, "%s", line->text_line);
- } else if (line->protocol == I3BAR && line->block_line) {
- double pos = tray_width - 0.5;
- bool edge = true;
- for (i = line->block_line->length - 1; i >= 0; --i) {
- struct status_block *block = line->block_line->items[i];
- if (block->full_text && block->full_text[0]) {
- render_block(window, config, block, &pos, edge, is_focused);
- edge = false;
- }
+ uint32_t max_height = 0;
+ /*
+ * Each render_* function takes the actual height of the bar, and returns
+ * the ideal height. If the actual height is too short, the render function
+ * can do whatever it wants - the buffer won't be committed. If the actual
+ * height is too tall, the render function should adapt its drawing to
+ * utilize the available space.
+ */
+ double x = output->width * output->scale;
+ if (bar->status) {
+ uint32_t h = render_status_line(cairo, config, output,
+ bar->status, output->focused, &x, output->height);
+ max_height = h > max_height ? h : max_height;
+ }
+ x = 0;
+ if (config->workspace_buttons) {
+ struct swaybar_workspace *ws;
+ wl_list_for_each_reverse(ws, &output->workspaces, link) {
+ uint32_t h = render_workspace_button(cairo,
+ output, config, ws, &x, output->height);
+ max_height = h > max_height ? h : max_height;
}
}
+ if (config->binding_mode_indicator && config->mode) {
+ uint32_t h = render_binding_mode_indicator(cairo,
+ output, config, config->mode, x, output->height);
+ max_height = h > max_height ? h : max_height;
+ }
- cairo_set_line_width(cairo, 1.0);
- double x = 0.5;
+ return max_height > output->height ? max_height : output->height;
+}
- // Workspaces
- if (config->workspace_buttons) {
- for (i = 0; i < output->workspaces->length; ++i) {
- struct workspace *ws = output->workspaces->items[i];
- render_workspace_button(window, config, ws, &x);
+void render_frame(struct swaybar *bar, struct swaybar_output *output) {
+ struct swaybar_hotspot *hotspot, *tmp;
+ wl_list_for_each_safe(hotspot, tmp, &output->hotspots, link) {
+ if (hotspot->destroy) {
+ hotspot->destroy(hotspot->data);
}
+ wl_list_remove(&hotspot->link);
+ free(hotspot);
}
- // binding mode indicator
- if (config->mode && config->binding_mode_indicator) {
- render_binding_mode_indicator(window, config, x);
+ cairo_surface_t *recorder = cairo_recording_surface_create(
+ CAIRO_CONTENT_COLOR_ALPHA, NULL);
+ cairo_t *cairo = cairo_create(recorder);
+ cairo_save(cairo);
+ cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR);
+ cairo_paint(cairo);
+ cairo_restore(cairo);
+ uint32_t height = render_to_cairo(cairo, bar, output);
+ if (bar->config->height >= 0 && height < (uint32_t)bar->config->height) {
+ height = bar->config->height;
}
-}
-
-void set_window_height(struct window *window, int height) {
- int text_width, text_height;
- get_text_size(window->cairo, window->font,
- &text_width, &text_height, window->scale, false,
- "Test string for measuring purposes");
- if (height > 0) {
- margin = (height - text_height) / 2;
- ws_vertical_padding = margin - 1.5;
- }
- window->height = (text_height + margin * 2) / window->scale;
+ if (height != output->height) {
+ // Reconfigure surface
+ zwlr_layer_surface_v1_set_size(output->layer_surface, 0, height);
+ zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, height);
+ // TODO: this could infinite loop if the compositor assigns us a
+ // different height than what we asked for
+ wl_surface_commit(output->surface);
+ wl_display_roundtrip(bar->display);
+ } else {
+ // Replay recording into shm and send it off
+ output->current_buffer = get_next_buffer(bar->shm,
+ output->buffers,
+ output->width * output->scale,
+ output->height * output->scale);
+ cairo_t *shm = output->current_buffer->cairo;
+
+ cairo_save(shm);
+ cairo_set_operator(shm, CAIRO_OPERATOR_CLEAR);
+ cairo_paint(shm);
+ cairo_restore(shm);
+
+ cairo_set_source_surface(shm, recorder, 0.0, 0.0);
+ cairo_paint(shm);
+
+ wl_surface_set_buffer_scale(output->surface, output->scale);
+ wl_surface_attach(output->surface,
+ output->current_buffer->buffer, 0, 0);
+ wl_surface_damage(output->surface, 0, 0,
+ output->width, output->height);
+ wl_surface_commit(output->surface);
+ wl_display_roundtrip(bar->display);
+ }
+ cairo_surface_destroy(recorder);
+ cairo_destroy(cairo);
}