int width = view->current.width;
int corner_width = ssd_get_corner_width();
- float *color;
struct wlr_scene_tree *parent;
+ struct wlr_buffer *titlebar_fill;
struct wlr_buffer *corner_top_left;
struct wlr_buffer *corner_top_right;
int active;
parent = subtree->tree;
active = (subtree == &ssd->titlebar.active) ?
THEME_ACTIVE : THEME_INACTIVE;
- color = theme->window[active].title_bg_color;
+ titlebar_fill = &theme->window[active].titlebar_fill->base;
corner_top_left = &theme->window[active].corner_top_left_normal->base;
corner_top_right = &theme->window[active].corner_top_right_normal->base;
wlr_scene_node_set_enabled(&parent->node, active);
wl_list_init(&subtree->parts);
/* Background */
- add_scene_rect(&subtree->parts, LAB_SSD_PART_TITLEBAR, parent,
- MAX(width - corner_width * 2, 0), theme->titlebar_height,
- corner_width, 0, color);
+ add_scene_buffer(&subtree->parts, LAB_SSD_PART_TITLEBAR, parent,
+ titlebar_fill, corner_width, 0);
add_scene_buffer(&subtree->parts, LAB_SSD_PART_TITLEBAR_CORNER_LEFT, parent,
corner_top_left, -rc.theme->border_width, -rc.theme->border_width);
add_scene_buffer(&subtree->parts, LAB_SSD_PART_TITLEBAR_CORNER_RIGHT, parent,
FOR_EACH_STATE(ssd, subtree) {
part = ssd_get_part(&subtree->parts, LAB_SSD_PART_TITLEBAR);
wlr_scene_node_set_position(part->node, x, 0);
- wlr_scene_rect_set_size(wlr_scene_rect_from_node(part->node),
+ wlr_scene_buffer_set_dest_size(
+ wlr_scene_buffer_from_node(part->node),
MAX(width - 2 * x, 0), theme->titlebar_height);
part = ssd_get_part(&subtree->parts, LAB_SSD_PART_TITLEBAR_CORNER_LEFT);
int bg_offset = maximized || squared ? 0 : corner_width;
FOR_EACH_STATE(ssd, subtree) {
part = ssd_get_part(&subtree->parts, LAB_SSD_PART_TITLEBAR);
- wlr_scene_rect_set_size(
- wlr_scene_rect_from_node(part->node),
+ wlr_scene_buffer_set_dest_size(
+ wlr_scene_buffer_from_node(part->node),
MAX(width - bg_offset * 2, 0), theme->titlebar_height);
x = theme->window_titlebar_padding_width;
bool title_unchanged = state->text && !strcmp(title, state->text);
const float *text_color;
- const float *bg_color;
+ const float bg_color[4] = {0, 0, 0, 0}; /* ignored */
struct font *font = NULL;
struct ssd_part *part;
struct ssd_sub_tree *subtree;
THEME_ACTIVE : THEME_INACTIVE;
dstate = active ? &state->active : &state->inactive;
text_color = theme->window[active].label_text_color;
- bg_color = theme->window[active].title_bg_color;
font = active ? &rc.font_activewindow : &rc.font_inactivewindow;
if (title_bg_width <= 0) {
if (!part) {
/* Initialize part and wlr_scene_buffer without attaching a buffer */
part = add_scene_part(&subtree->parts, LAB_SSD_PART_TITLE);
- part->buffer = scaled_font_buffer_create(subtree->tree);
+ part->buffer = scaled_font_buffer_create_for_titlebar(
+ subtree->tree, theme->titlebar_height,
+ theme->window[active].titlebar_pattern);
if (part->buffer) {
part->node = &part->buffer->scene_buffer->node;
} else {
struct wlr_box *box;
double radius;
double line_width;
- float *fill_color;
+ cairo_pattern_t *fill_pattern;
float *border_color;
enum corner corner;
};
}
cairo_close_path(cairo);
cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
- set_cairo_color(cairo, ctx->fill_color);
+ /*
+ * We need to offset the fill pattern vertically by the border
+ * width to line up with the rest of the titlebar. This is done
+ * by applying a transformation matrix to the pattern temporarily.
+ * It would be better to copy the pattern, but cairo does not
+ * provide a simple way to this.
+ */
+ cairo_matrix_t matrix;
+ cairo_matrix_init_translate(&matrix, 0, -ctx->line_width);
+ cairo_pattern_set_matrix(ctx->fill_pattern, &matrix);
+ cairo_set_source(cairo, ctx->fill_pattern);
cairo_fill_preserve(cairo);
cairo_stroke(cairo);
+ /* Reset the fill pattern transformation matrix afterward */
+ cairo_matrix_init_identity(&matrix);
+ cairo_pattern_set_matrix(ctx->fill_pattern, &matrix);
+
/*
* Stroke horizontal and vertical borders, shown by Xs and Ys
* respectively in the figure below:
return buffer;
}
+static struct lab_data_buffer *
+create_titlebar_fill(cairo_pattern_t *pattern, int height)
+{
+ /* create 1px wide buffer to be stretched horizontally */
+ struct lab_data_buffer *fill = buffer_create_cairo(1, height, 1);
+
+ cairo_t *cairo = cairo_create(fill->surface);
+ cairo_set_source(cairo, pattern);
+ cairo_paint(cairo);
+ cairo_surface_flush(fill->surface);
+ cairo_destroy(cairo);
+
+ return fill;
+}
+
+static void
+create_backgrounds(struct theme *theme)
+{
+ for (int active = THEME_INACTIVE; active <= THEME_ACTIVE; active++) {
+ theme->window[active].titlebar_pattern = color_to_pattern(
+ theme->window[active].title_bg_color);
+ theme->window[active].titlebar_fill = create_titlebar_fill(
+ theme->window[active].titlebar_pattern,
+ theme->titlebar_height);
+ }
+}
+
static void
create_corners(struct theme *theme)
{
.box = &box,
.radius = rc.corner_radius,
.line_width = theme->border_width,
- .fill_color = theme->window[active].title_bg_color,
+ .fill_pattern = theme->window[active].titlebar_pattern,
.border_color = theme->window[active].border_color,
.corner = LAB_CORNER_TOP_LEFT,
};
paths_destroy(&paths);
post_processing(theme);
+ create_backgrounds(theme);
create_corners(theme);
load_buttons(theme);
create_shadows(theme);
}
for (int active = THEME_INACTIVE; active <= THEME_ACTIVE; active++) {
+ zfree_pattern(theme->window[active].titlebar_pattern);
+ zdrop(&theme->window[active].titlebar_fill);
zdrop(&theme->window[active].corner_top_left_normal);
zdrop(&theme->window[active].corner_top_right_normal);
zdrop(&theme->window[active].shadow_corner_top);