ssd: rework titlebar button rendering

- fix that icons for normal/hovered/rounded buttons are not placed
  exactly the same position
- fix blurry window button icons in scaled outputs

This commit introduces lab_img and scaled_img_buffer and uses them for
rendering icons in the window titlebar. Now the process of rendering
button icons are split into 2 phases: loading with lab_img_load() and
creating scene-nodes for them with scaled_img_buffer_create(). This
might incur some additional overhead since we no longer preload icon
textures, but the rendering of icon only happens for the first window
as backing buffers are shared and the overhead won't be noticeable.
This commit also simplifies the process of centering icon buffer in the
button, by creating icon buffers in a fixed geometry via
lab_img_render().
This commit is contained in:
tokyo4j 2024-11-28 19:21:18 +09:00 committed by Hiroaki Yamamoto
parent 9a3412324d
commit 16dbdc64e5
25 changed files with 647 additions and 391 deletions

View file

@ -49,27 +49,27 @@ box_union(struct wlr_box *box_dest, struct wlr_box *box_a, struct wlr_box *box_b
}
struct wlr_box
box_fit_within(int width, int height, int max_width, int max_height)
box_fit_within(int width, int height, struct wlr_box *bound)
{
struct wlr_box box;
if (width <= max_width && height <= max_height) {
if (width <= bound->width && height <= bound->height) {
/* No downscaling needed */
box.width = width;
box.height = height;
} else if (width * max_height > height * max_width) {
} else if (width * bound->height > height * bound->width) {
/* Wider content, fit width */
box.width = max_width;
box.height = (height * max_width + (width / 2)) / width;
box.width = bound->width;
box.height = (height * bound->width + (width / 2)) / width;
} else {
/* Taller content, fit height */
box.width = (width * max_height + (height / 2)) / height;
box.height = max_height;
box.width = (width * bound->height + (height / 2)) / height;
box.height = bound->height;
}
/* Compute centered position */
box.x = (max_width - box.width) / 2;
box.y = (max_height - box.height) / 2;
box.x = bound->x + (bound->width - box.width) / 2;
box.y = bound->y + (bound->height - box.height) / 2;
return box;
}

View file

@ -14,6 +14,7 @@ labwc_sources += files(
'parse-bool.c',
'parse-double.c',
'scaled-font-buffer.c',
'scaled-img-buffer.c',
'scaled-rect-buffer.c',
'scaled-scene-buffer.c',
'scene-helpers.c',

View file

@ -0,0 +1,90 @@
// SPDX-License-Identifier: GPL-2.0-only
#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include <wayland-server-core.h>
#include <wlr/types/wlr_scene.h>
#include "buffer.h"
#include "common/list.h"
#include "common/mem.h"
#include "common/scaled-img-buffer.h"
#include "common/scaled-scene-buffer.h"
#include "img/img.h"
#include "node.h"
static struct wl_list cached_buffers = WL_LIST_INIT(&cached_buffers);
static struct lab_data_buffer *
_create_buffer(struct scaled_scene_buffer *scaled_buffer, double scale)
{
struct scaled_img_buffer *self = scaled_buffer->data;
struct lab_data_buffer *buffer = lab_img_render(self->img,
self->width, self->height, self->padding, scale);
return buffer;
}
static void
_destroy(struct scaled_scene_buffer *scaled_buffer)
{
struct scaled_img_buffer *self = scaled_buffer->data;
free(self);
}
static bool
_equal(struct scaled_scene_buffer *scaled_buffer_a,
struct scaled_scene_buffer *scaled_buffer_b)
{
struct scaled_img_buffer *a = scaled_buffer_a->data;
struct scaled_img_buffer *b = scaled_buffer_b->data;
return a->img == b->img
&& a->width == b->width
&& a->height == b->height
&& a->padding == b->padding;
}
static struct scaled_scene_buffer_impl impl = {
.create_buffer = _create_buffer,
.destroy = _destroy,
.equal = _equal,
};
struct scaled_img_buffer *
scaled_img_buffer_create(struct wlr_scene_tree *parent, struct lab_img *img,
int width, int height, int padding)
{
struct scaled_scene_buffer *scaled_buffer = scaled_scene_buffer_create(
parent, &impl, &cached_buffers, /* drop_buffer */ true);
struct scaled_img_buffer *self = znew(*self);
self->scaled_buffer = scaled_buffer;
self->scene_buffer = scaled_buffer->scene_buffer;
self->img = img;
self->width = width;
self->height = height;
self->padding = padding;
scaled_buffer->data = self;
scaled_scene_buffer_request_update(scaled_buffer, width, height);
return self;
}
void
scaled_img_buffer_update(struct scaled_img_buffer *self, struct lab_img *img,
int width, int height, int padding)
{
self->img = img;
self->width = width;
self->height = height;
self->padding = padding;
scaled_scene_buffer_request_update(self->scaled_buffer, width, height);
}
struct scaled_img_buffer *
scaled_img_buffer_from_node(struct wlr_scene_node *node)
{
struct scaled_scene_buffer *scaled_buffer =
node_scaled_scene_buffer_from_node(node);
assert(scaled_buffer->impl == &impl);
return scaled_buffer->data;
}