*/
int font_width(struct font *font, const char *string);
+/**
+ * font_get_buffer_size - dry-run font_buffer_create() to get buffer size
+ */
+void font_get_buffer_size(int max_width, const char *text, struct font *font,
+ int *width, int *height);
+
/**
* font_buffer_create - Create ARGB8888 lab_data_buffer using pango
* @buffer: buffer pointer
const struct scaled_scene_buffer_impl *implementation,
struct wl_list *cached_buffers, bool drop_buffer);
-/* Clear the cache of existing buffers, useful in case the content changes */
-void scaled_scene_buffer_invalidate_cache(struct scaled_scene_buffer *self);
+/**
+ * scaled_scene_buffer_request_update - mark the buffer that needs to be
+ * updated
+ * @width: the width of the buffer to be rendered, in scene coordinates
+ * @height: the height of the buffer to be rendered, in scene coordinates
+ *
+ * This function should be called when the states bound to the buffer are
+ * updated and ready for rendering.
+ */
+void scaled_scene_buffer_request_update(struct scaled_scene_buffer *self,
+ int width, int height);
/* Private */
struct scaled_scene_buffer_cache_entry {
return rectangle.width;
}
+void
+font_get_buffer_size(int max_width, const char *text, struct font *font,
+ int *width, int *height)
+{
+ PangoRectangle text_extents = font_extents(font, text);
+ if (max_width > 0 && text_extents.width > max_width) {
+ text_extents.width = max_width;
+ }
+ *width = text_extents.width;
+ *height = text_extents.height;
+}
+
void
font_buffer_create(struct lab_data_buffer **buffer, int max_width,
const char *text, struct font *font, const float *color,
return;
}
- PangoRectangle text_extents = font_extents(font, text);
-
- if (max_width > 0 && text_extents.width > max_width) {
- text_extents.width = max_width;
- }
+ int width, height;
+ font_get_buffer_size(max_width, text, font, &width, &height);
- *buffer = buffer_create_cairo(text_extents.width, text_extents.height, scale);
+ *buffer = buffer_create_cairo(width, height, scale);
if (!*buffer) {
wlr_log(WLR_ERROR, "Failed to create font buffer");
return;
PangoLayout *layout = pango_cairo_create_layout(cairo);
pango_context_set_round_glyph_positions(pango_layout_get_context(layout), false);
- pango_layout_set_width(layout, text_extents.width * PANGO_SCALE);
+ pango_layout_set_width(layout, width * PANGO_SCALE);
pango_layout_set_text(layout, text, -1);
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
memcpy(self->color, color, sizeof(self->color));
memcpy(self->bg_color, bg_color, sizeof(self->bg_color));
- /* Invalidate cache and force a new render */
- scaled_scene_buffer_invalidate_cache(self->scaled_buffer);
-
- /* Ensure the height / width is up-to-date */
- self->width = self->scaled_buffer->width;
- self->height = self->scaled_buffer->height;
+ /* Calculate the size of font buffer and request re-rendering */
+ font_get_buffer_size(self->max_width, self->text, &self->font,
+ &self->width, &self->height);
+ scaled_scene_buffer_request_update(self->scaled_buffer,
+ self->width, self->height);
}
void
scaled_font_buffer_set_max_width(struct scaled_font_buffer *self, int max_width)
{
self->max_width = max_width;
- scaled_scene_buffer_invalidate_cache(self->scaled_buffer);
- /* Ensure the height / width is up-to-date */
- self->width = self->scaled_buffer->width;
- self->height = self->scaled_buffer->height;
+ font_get_buffer_size(self->max_width, self->text, &self->font,
+ &self->width, &self->height);
+ scaled_scene_buffer_request_update(self->scaled_buffer,
+ self->width, self->height);
}
memcpy(self->fill_color, fill_color, sizeof(self->fill_color));
memcpy(self->border_color, border_color, sizeof(self->border_color));
- scaled_scene_buffer_invalidate_cache(scaled_buffer);
+ scaled_scene_buffer_request_update(scaled_buffer,
+ self->width, self->height);
return self;
}
}
self->impl = impl;
- self->active_scale = 1;
+ /*
+ * Set active scale to zero so that we always render a new buffer when
+ * entering the first output
+ */
+ self->active_scale = 0;
self->drop_buffer = drop_buffer;
wl_list_init(&self->cache);
}
void
-scaled_scene_buffer_invalidate_cache(struct scaled_scene_buffer *self)
+scaled_scene_buffer_request_update(struct scaled_scene_buffer *self,
+ int width, int height)
{
assert(self);
struct scaled_scene_buffer_cache_entry *cache_entry, *cache_entry_tmp;
_cache_entry_destroy(cache_entry, self->drop_buffer);
}
assert(wl_list_empty(&self->cache));
- _update_buffer(self, self->active_scale);
+
+ /*
+ * Tell wlroots about the buffer size so we can receive output_enter
+ * events even when the actual backing buffer is not set yet.
+ * The buffer size set here is updated when the backing buffer is
+ * created in _update_buffer().
+ */
+ wlr_scene_buffer_set_dest_size(self->scene_buffer, width, height);
+ self->width = width;
+ self->height = height;
+
+ /*
+ * Skip re-rendering if the buffer is not shown yet
+ * TODO: don't re-render also when the buffer is temporarily invisible
+ */
+ if (self->active_scale > 0) {
+ _update_buffer(self, self->active_scale);
+ }
}