feat(backend): 添加创建 bar 窗口接口

This commit is contained in:
2026-06-05 19:03:47 +08:00
parent f540c07aad
commit e9366b64e2
5 changed files with 144 additions and 0 deletions

View File

@@ -76,6 +76,9 @@ pkg_check_modules(deps REQUIRED
xcb-xfixes
xcb-xinerama
xkbcommon
cairo
cairo-xcb
)
target_include_directories(${APP_NAME} SYSTEM

View File

@@ -1,5 +1,7 @@
#include "core/backend.h"
#include <cairo-xcb.h>
#include <cairo.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
@@ -678,3 +680,70 @@ void backend_scan_result_destroy(backend_scan_result_t *result) {
p_delete(&result->windows);
p_delete(&result);
}
backend_bar_window_t backend_create_bar_window(
backend_t *backend,
rect_t geometry,
uint32_t bg_pixel
) {
auto conn = backend->conn;
auto root = backend->screen->root;
auto visual = window_get_visual(backend, true);
xcb_grab_server(conn);
window_clean_event_mask(conn, root);
auto window_id = xcb_generate_id(conn);
uint16_t _class = XCB_WINDOW_CLASS_INPUT_OUTPUT;
uint32_t event_mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_BACK_PIXEL |
XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK;
const xcb_create_window_value_list_t value_list = {
.override_redirect = true,
.background_pixel = bg_pixel,
.border_pixel = 0,
.event_mask = XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_EXPOSURE,
};
auto cookie = xcb_create_window_aux_checked(
conn,
visual->depth,
window_id,
root,
geometry.x,
geometry.y,
geometry.width,
geometry.height,
0,
_class,
visual->visual->visual_id,
event_mask,
&value_list
);
if (xcb_request_check(conn, cookie)) fatal("cannot create bar window");
cookie = xcb_map_window_checked(conn, window_id);
if (xcb_request_check(conn, cookie)) fatal("cannot map bar window");
window_set_class_instance(conn, window_id);
window_set_name_static(conn, window_id, APP_NAME "_bar");
root_set_event_mask(backend);
xcb_ungrab_server(conn);
xcb_aux_sync(conn);
auto width = geometry.width;
auto height = geometry.height;
auto vid = visual->visual;
auto surface = cairo_xcb_surface_create(conn, window_id, vid, width, height);
auto cr = cairo_create(surface);
cairo_surface_destroy(surface);
p_delete(&visual);
auto statue = cairo_status(cr);
if (statue != CAIRO_STATUS_SUCCESS) {
fatal("cannot create cairo context: %s", cairo_status_to_string(statue));
}
return (backend_bar_window_t){.window_id = window_id, .cr = cr};
}

View File

@@ -405,3 +405,49 @@ void window_grab_keys(
p_delete(&keycodes);
}
}
static visual_t *get_alpha_visual(backend_t *backend) {
auto depth_iter = xcb_screen_allowed_depths_iterator(backend->screen);
for (; depth_iter.rem; xcb_depth_next(&depth_iter)) {
if (depth_iter.data->depth != 32) continue;
auto visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
for (; visual_iter.rem; xcb_visualtype_next(&visual_iter)) {
if (visual_iter.data->_class == XCB_VISUAL_CLASS_TRUE_COLOR) {
auto visual = p_new(visual_t, 1);
visual->visual = visual_iter.data;
visual->depth = depth_iter.data->depth;
return visual;
}
}
}
return nullptr;
}
static visual_t *get_root_visual(backend_t *backend) {
auto depth_iter = xcb_screen_allowed_depths_iterator(backend->screen);
auto visual_id = backend->screen->root_visual;
for (; depth_iter.rem; xcb_depth_next(&depth_iter)) {
auto visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
for (; visual_iter.rem; xcb_visualtype_next(&visual_iter)) {
if (visual_iter.data->visual_id == visual_id) {
auto visual = p_new(visual_t, 1);
visual->visual = visual_iter.data;
visual->depth = depth_iter.data->depth;
return visual;
}
}
}
return nullptr;
}
visual_t *window_get_visual(backend_t *backend, bool prefer_alpha) {
if (!prefer_alpha) return get_root_visual(backend);
auto visual = get_alpha_visual(backend);
if (!visual) visual = get_root_visual(backend);
return visual;
}

View File

@@ -104,3 +104,17 @@ void window_grab_keys(
const key_bind_t *keys,
size_t count
);
typedef struct visual_t {
uint8_t depth;
xcb_visualtype_t *visual;
} visual_t;
/**
* @brief 获取 xcb 的 visual 及其对应的 depth
*
* @param prefer_alpha 支持 alpha 的 visual 优先
*
* @returns 返回的信息使用后记得使用 free 释放
*/
visual_t *window_get_visual(backend_t *backend, bool prefer_alpha);

View File

@@ -1,5 +1,6 @@
#pragma once
#include <cairo.h>
#include <stddef.h>
#include "core/event.h"
@@ -51,3 +52,14 @@ typedef struct backend_scan_result_t {
*/
backend_scan_result_t *backend_scan_windows(backend_t *backend);
void backend_scan_result_destroy(backend_scan_result_t *result);
typedef struct backend_bar_window_t {
window_id_t window_id;
cairo_t *cr;
} backend_bar_window_t;
backend_bar_window_t backend_create_bar_window(
backend_t *backend,
rect_t geometry,
uint32_t bg_pixel
);