static void render_details_scroll_button(cairo_t *cairo, struct swaynag *swaynag, struct swaynag_button *button) { int text_width, text_height; get_text_size(cairo, swaynag->type->font, &text_width, &text_height, NULL, swaynag->scale, true, "%s", button->text); int border = swaynag->type->button_border_thickness * swaynag->scale; int padding = swaynag->type->button_padding * swaynag->scale; cairo_set_source_u32(cairo, swaynag->type->border); cairo_rectangle(cairo, button->x, button->y, button->width, button->height); cairo_fill(cairo); cairo_set_source_u32(cairo, swaynag->type->button_background); cairo_rectangle(cairo, button->x + border, button->y + border, button->width - (border * 2), button->height - (border * 2)); cairo_fill(cairo); cairo_set_source_u32(cairo, swaynag->type->text); cairo_move_to(cairo, button->x + border + padding, button->y + border + (button->height - text_height) / 2); pango_printf(cairo, swaynag->type->font, swaynag->scale, true, "%s", button->text); }
void render(struct output *output, struct config *config, struct status_line *line) { int i; struct window *window = output->window; cairo_t *cairo = window->cairo; // Clear cairo_save(cairo); cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); cairo_paint(cairo); cairo_restore(cairo); // Background cairo_set_source_u32(cairo, config->colors.background); cairo_paint(cairo); // Command output cairo_set_source_u32(cairo, config->colors.statusline); int width, height; if (line->protocol == TEXT) { get_text_size(window->cairo, window->font, &width, &height, "%s", line->text_line); cairo_move_to(cairo, window->width - margin - width, margin); pango_printf(window->cairo, window->font, "%s", line->text_line); } else if (line->protocol == I3BAR && line->block_line) { double pos = window->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); edge = false; } } } cairo_set_line_width(cairo, 1.0); double x = 0.5; // 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); } } // binding mode indicator if (config->mode && config->binding_mode_indicator) { render_binding_mode_indicator(window, config, x); } }
static uint32_t render_message(cairo_t *cairo, struct swaynag *swaynag) { int text_width, text_height; get_text_size(cairo, swaynag->type->font, &text_width, &text_height, NULL, swaynag->scale, true, "%s", swaynag->message); int padding = swaynag->type->message_padding * swaynag->scale; uint32_t ideal_height = text_height + padding * 2; uint32_t ideal_surface_height = ideal_height / swaynag->scale; if (swaynag->height < ideal_surface_height) { return ideal_surface_height; } cairo_set_source_u32(cairo, swaynag->type->text); cairo_move_to(cairo, padding, (int)(ideal_height - text_height) / 2); pango_printf(cairo, swaynag->type->font, swaynag->scale, false, "%s", swaynag->message); return ideal_surface_height; }
static uint32_t render_button(cairo_t *cairo, struct swaynag *swaynag, int button_index, int *x) { struct swaynag_button *button = swaynag->buttons->items[button_index]; int text_width, text_height; get_text_size(cairo, swaynag->type->font, &text_width, &text_height, NULL, swaynag->scale, true, "%s", button->text); int border = swaynag->type->button_border_thickness * swaynag->scale; int padding = swaynag->type->button_padding * swaynag->scale; uint32_t ideal_height = text_height + padding * 2 + border * 2; uint32_t ideal_surface_height = ideal_height / swaynag->scale; if (swaynag->height < ideal_surface_height) { return ideal_surface_height; } button->x = *x - border - text_width - padding * 2 + 1; button->y = (int)(ideal_height - text_height) / 2 - padding + 1; button->width = text_width + padding * 2; button->height = text_height + padding * 2; cairo_set_source_u32(cairo, swaynag->type->border); cairo_rectangle(cairo, button->x - border, button->y - border, button->width + border * 2, button->height + border * 2); cairo_fill(cairo); cairo_set_source_u32(cairo, swaynag->type->button_background); cairo_rectangle(cairo, button->x, button->y, button->width, button->height); cairo_fill(cairo); cairo_set_source_u32(cairo, swaynag->type->text); cairo_move_to(cairo, button->x + padding, button->y + padding); pango_printf(cairo, swaynag->type->font, swaynag->scale, true, "%s", button->text); *x = button->x - border; 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, "%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, "%s", config->mode); }
static int draw_node(cairo_t *cairo, struct sway_node *node, struct sway_node *focus, int x, int y) { int text_width, text_height; char *buffer = get_string(node); get_text_size(cairo, "monospace", &text_width, &text_height, NULL, 1, false, buffer); cairo_save(cairo); cairo_rectangle(cairo, x + 2, y, text_width - 2, text_height); cairo_set_source_u32(cairo, 0xFFFFFFE0); cairo_fill(cairo); int height = text_height; list_t *children = get_children(node); if (children) { for (int i = 0; i < children->length; ++i) { // This is really dirty - the list contains specific structs but // we're casting them as nodes. This works because node is the first // item in each specific struct. This is acceptable because this is // debug code. struct sway_node *child = children->items[i]; if (node_get_parent(child) == node) { cairo_set_source_u32(cairo, 0x000000FF); } else { cairo_set_source_u32(cairo, 0xFF0000FF); } height += draw_node(cairo, child, focus, x + 10, y + height); } } cairo_set_source_u32(cairo, 0xFFFFFFE0); cairo_rectangle(cairo, x, y, 2, height); cairo_fill(cairo); cairo_restore(cairo); cairo_move_to(cairo, x, y); if (focus == node) { cairo_set_source_u32(cairo, 0x0000FFFF); } pango_printf(cairo, "monospace", 1, false, buffer); free(buffer); return height; }
static void render_workspace_button(struct window *window, struct config *config, struct workspace *ws, double *x) { // strip workspace numbers if required char *name = handle_workspace_number(config->strip_workspace_numbers, ws->name); int width, height; get_text_size(window->cairo, window->font, &width, &height, "%s", name); struct box_colors box_colors; if (ws->urgent) { box_colors = config->colors.urgent_workspace; } else if (ws->focused) { box_colors = config->colors.focused_workspace; } else if (ws->visible) { box_colors = config->colors.active_workspace; } else { box_colors = config->colors.inactive_workspace; } // background cairo_set_source_u32(window->cairo, box_colors.background); cairo_rectangle(window->cairo, *x, 1.5, width + ws_horizontal_padding * 2 - 1, height + ws_vertical_padding * 2); cairo_fill(window->cairo); // border cairo_set_source_u32(window->cairo, box_colors.border); cairo_rectangle(window->cairo, *x, 1.5, width + ws_horizontal_padding * 2 - 1, height + ws_vertical_padding * 2); 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, "%s", name); *x += width + ws_horizontal_padding * 2 + ws_spacing; free(name); }
static void render_block(struct window *window, struct config *config, struct status_block *block, double *x, bool edge) { int width, height, sep_width; get_text_size(window->cairo, window->font, &width, &height, "%s", block->full_text); int textwidth = width; double block_width = width; if (width < block->min_width) { width = block->min_width; } *x -= width; if (block->border != 0 && block->border_left > 0) { *x -= (block->border_left + margin); block_width += block->border_left + margin; } if (block->border != 0 && block->border_right > 0) { *x -= (block->border_right + margin); block_width += block->border_right + margin; } // Add separator if (!edge) { if (config->sep_symbol) { get_text_size(window->cairo, window->font, &sep_width, &height, "%s", config->sep_symbol); 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; // 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 - 2); cairo_fill(window->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); } // render bottom border if (block->border != 0 && block->border_bottom > 0) { render_sharp_line(window->cairo, block->border, pos - 0.5, window->height - 1 - 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 - 2); 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; } else if (strncmp(block->align, "center", 6) == 0) { offset = pos + (width - textwidth) / 2; } cairo_move_to(window->cairo, offset, margin); cairo_set_source_u32(window->cairo, block->color); pango_printf(window->cairo, window->font, "%s", block->full_text); pos += width; // render right border if (block->border != 0 && block->border_right > 0) { pos += margin; render_sharp_line(window->cairo, block->border, pos - 0.5, 1, block->border_right, window->height - 2); pos += block->border_right; } // render separator if (!edge && block->separator) { cairo_set_source_u32(window->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, "%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 - margin); cairo_stroke(window->cairo); } } }