mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-06-19 14:33:16 -04:00
feat: text node support
This commit is contained in:
parent
24fb167ae6
commit
5c6cf39901
4 changed files with 188 additions and 0 deletions
|
|
@ -37,6 +37,9 @@ pcre2_dep = dependency('libpcre2-8')
|
|||
libscenefx_dep = dependency('scenefx-0.4',version: '>=0.4.1')
|
||||
pixman_dep = dependency('pixman-1')
|
||||
cjson_dep = dependency('libcjson')
|
||||
cairo_dep = dependency('cairo')
|
||||
pango_dep = dependency('pango')
|
||||
pangocairo_dep = dependency('pangocairo')
|
||||
|
||||
# version info
|
||||
git = find_program('git', required : false)
|
||||
|
|
@ -94,6 +97,7 @@ endif
|
|||
executable('mango',
|
||||
'src/mango.c',
|
||||
'src/common/util.c',
|
||||
'src/draw/text-node.c',
|
||||
'src/ext-protocol/wlr_ext_workspace_v1.c',
|
||||
wayland_sources,
|
||||
dependencies : [
|
||||
|
|
@ -109,6 +113,9 @@ executable('mango',
|
|||
pcre2_dep,
|
||||
pixman_dep,
|
||||
cjson_dep,
|
||||
cairo_dep,
|
||||
pango_dep,
|
||||
pangocairo_dep,
|
||||
],
|
||||
install : true,
|
||||
c_args : c_args,
|
||||
|
|
|
|||
140
src/draw/text-node.c
Normal file
140
src/draw/text-node.c
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
#include "text-node.h"
|
||||
#include <stdlib.h>
|
||||
#include <cairo.h>
|
||||
#include <pango/pangocairo.h>
|
||||
#include <wlr/interfaces/wlr_buffer.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
// 自定义 wlr_buffer,用于将 Cairo Surface 包装并注入 wlr_scene
|
||||
struct mango_text_buffer {
|
||||
struct wlr_buffer base;
|
||||
cairo_surface_t *surface;
|
||||
};
|
||||
|
||||
static void text_buffer_destroy(struct wlr_buffer *wlr_buffer) {
|
||||
struct mango_text_buffer *buf = wl_container_of(wlr_buffer, buf, base);
|
||||
cairo_surface_destroy(buf->surface);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
static bool text_buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer,
|
||||
uint32_t flags,
|
||||
void **data,
|
||||
uint32_t *format,
|
||||
size_t *stride) {
|
||||
(void)flags; // 该参数当前无需使用
|
||||
struct mango_text_buffer *buf = wl_container_of(wlr_buffer, buf, base);
|
||||
*data = cairo_image_surface_get_data(buf->surface);
|
||||
*format = DRM_FORMAT_ARGB8888;
|
||||
*stride = cairo_image_surface_get_stride(buf->surface);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void text_buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer) {
|
||||
// Cairo 表面数据在 flush 后稳定,此处无需额外操作
|
||||
}
|
||||
|
||||
static const struct wlr_buffer_impl text_buffer_impl = {
|
||||
.destroy = text_buffer_destroy,
|
||||
.begin_data_ptr_access = text_buffer_begin_data_ptr_access,
|
||||
.end_data_ptr_access = text_buffer_end_data_ptr_access,
|
||||
};
|
||||
|
||||
struct mango_text_node *mango_text_node_create(struct wlr_scene_tree *parent) {
|
||||
struct mango_text_node *node = calloc(1, sizeof(*node));
|
||||
if (!node) return NULL;
|
||||
|
||||
node->scene_buffer = wlr_scene_buffer_create(parent, NULL);
|
||||
if (!node->scene_buffer) {
|
||||
free(node);
|
||||
return NULL;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
void mango_text_node_update(struct mango_text_node *node, const char *text,
|
||||
const char *font_desc, float color[4], float scale) {
|
||||
if (!node || !text || !font_desc) return;
|
||||
if (scale <= 0.0f) scale = 1.0f;
|
||||
|
||||
// 测量文字像素尺寸
|
||||
cairo_surface_t *dummy_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
|
||||
cairo_t *dummy_cr = cairo_create(dummy_surface);
|
||||
PangoContext *dummy_ctx = pango_cairo_create_context(dummy_cr);
|
||||
pango_cairo_context_set_resolution(dummy_ctx, 96.0 * scale);
|
||||
PangoLayout *dummy_layout = pango_layout_new(dummy_ctx);
|
||||
PangoFontDescription *desc = pango_font_description_from_string(font_desc);
|
||||
pango_layout_set_font_description(dummy_layout, desc);
|
||||
pango_layout_set_text(dummy_layout, text, -1);
|
||||
|
||||
int pixel_width, pixel_height;
|
||||
pango_layout_get_pixel_size(dummy_layout, &pixel_width, &pixel_height);
|
||||
|
||||
g_object_unref(dummy_layout);
|
||||
pango_font_description_free(desc);
|
||||
g_object_unref(dummy_ctx);
|
||||
cairo_destroy(dummy_cr);
|
||||
cairo_surface_destroy(dummy_surface);
|
||||
|
||||
if (pixel_width <= 0 || pixel_height <= 0) {
|
||||
wlr_scene_buffer_set_buffer(node->scene_buffer, NULL);
|
||||
node->logical_width = 0;
|
||||
node->logical_height = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建真实大小的 Surface 并绘制文字
|
||||
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, pixel_width, pixel_height);
|
||||
cairo_t *cr = cairo_create(surface);
|
||||
|
||||
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
|
||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_paint(cr);
|
||||
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
|
||||
|
||||
PangoContext *ctx = pango_cairo_create_context(cr);
|
||||
pango_cairo_context_set_resolution(ctx, 96.0 * scale);
|
||||
PangoLayout *layout = pango_layout_new(ctx);
|
||||
desc = pango_font_description_from_string(font_desc);
|
||||
pango_layout_set_font_description(layout, desc);
|
||||
pango_layout_set_text(layout, text, -1);
|
||||
|
||||
cairo_set_source_rgba(cr, color[0], color[1], color[2], color[3]);
|
||||
pango_cairo_show_layout(cr, layout);
|
||||
cairo_surface_flush(surface);
|
||||
|
||||
// 包装成 wlr_buffer
|
||||
struct mango_text_buffer *buf = calloc(1, sizeof(*buf));
|
||||
if (!buf) {
|
||||
cairo_surface_destroy(surface);
|
||||
cairo_destroy(cr);
|
||||
g_object_unref(layout);
|
||||
pango_font_description_free(desc);
|
||||
g_object_unref(ctx);
|
||||
return;
|
||||
}
|
||||
wlr_buffer_init(&buf->base, &text_buffer_impl, pixel_width, pixel_height);
|
||||
buf->surface = surface;
|
||||
|
||||
// 提交给场景图
|
||||
wlr_scene_buffer_set_buffer(node->scene_buffer, &buf->base);
|
||||
wlr_buffer_drop(&buf->base); // 函数内引用计数 -1,交给场景图管理
|
||||
|
||||
// 设置逻辑大小,实现 HiDPI 缩放
|
||||
node->logical_width = (int)(pixel_width / scale);
|
||||
node->logical_height = (int)(pixel_height / scale);
|
||||
wlr_scene_buffer_set_dest_size(node->scene_buffer, node->logical_width, node->logical_height);
|
||||
|
||||
// 清理绘制资源
|
||||
g_object_unref(layout);
|
||||
pango_font_description_free(desc);
|
||||
g_object_unref(ctx);
|
||||
cairo_destroy(cr);
|
||||
}
|
||||
|
||||
void mango_text_node_destroy(struct mango_text_node *node) {
|
||||
if (!node) return;
|
||||
wlr_scene_node_destroy(&node->scene_buffer->node);
|
||||
free(node);
|
||||
}
|
||||
34
src/draw/text-node.h
Normal file
34
src/draw/text-node.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef MANGO_TEXT_H
|
||||
#define MANGO_TEXT_H
|
||||
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
|
||||
struct mango_text_node {
|
||||
struct wlr_scene_buffer *scene_buffer;
|
||||
int logical_width;
|
||||
int logical_height;
|
||||
};
|
||||
|
||||
/**
|
||||
* 创建一个独立的文字场景节点
|
||||
* @param parent 父级场景树节点(例如窗口装饰树、OSD层树或状态栏树)
|
||||
*/
|
||||
struct mango_text_node *mango_text_node_create(struct wlr_scene_tree *parent);
|
||||
|
||||
/**
|
||||
* 更新节点中的文字内容、字体、颜色和缩放
|
||||
* @param node 文字节点指针
|
||||
* @param text 要显示的文本内容
|
||||
* @param font_desc Pango 字体描述字符串 (例如 "Sans 12" 或 "JetBrains Mono Bold 14")
|
||||
* @param color RGBA 颜色数组,范围 0.0 ~ 1.0
|
||||
* @param scale 当前输出设备的缩放比例 (HiDPI 支持)
|
||||
*/
|
||||
void mango_text_node_update(struct mango_text_node *node, const char *text,
|
||||
const char *font_desc, float color[4], float scale);
|
||||
|
||||
/**
|
||||
* 销毁文字节点并释放相关场景图资源
|
||||
*/
|
||||
void mango_text_node_destroy(struct mango_text_node *node);
|
||||
|
||||
#endif /* MANGO_TEXT_H */
|
||||
|
|
@ -96,6 +96,7 @@
|
|||
#include <xcb/xcb_icccm.h>
|
||||
#endif
|
||||
#include "common/util.h"
|
||||
#include "draw/text-node.h"
|
||||
|
||||
/* macros */
|
||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||
|
|
@ -327,6 +328,7 @@ struct Client {
|
|||
struct wlr_scene_shadow *shadow;
|
||||
struct wlr_scene_tree *scene_surface;
|
||||
struct wlr_scene_tree *overview_scene_surface;
|
||||
struct mango_text_node *text_node;
|
||||
struct wl_list link;
|
||||
struct wl_list flink;
|
||||
struct wl_list fadeout_link;
|
||||
|
|
@ -4513,6 +4515,11 @@ mapnotify(struct wl_listener *listener, void *data) {
|
|||
#endif
|
||||
// extra node
|
||||
|
||||
c->text_node = mango_text_node_create(c->scene);
|
||||
mango_text_node_update(c->text_node, "hello world", "Sans 50", config.focuscolor, 1.0f);
|
||||
wlr_scene_node_lower_to_bottom(&c->text_node->scene_buffer->node);
|
||||
wlr_scene_node_set_enabled(&c->text_node->scene_buffer->node, false);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
c->splitindicator[i] = wlr_scene_rect_create(
|
||||
c->scene, 0, 0,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue