feat(backend): 添加创建 bar 窗口接口
This commit is contained in:
@@ -76,6 +76,9 @@ pkg_check_modules(deps REQUIRED
|
|||||||
xcb-xfixes
|
xcb-xfixes
|
||||||
xcb-xinerama
|
xcb-xinerama
|
||||||
xkbcommon
|
xkbcommon
|
||||||
|
|
||||||
|
cairo
|
||||||
|
cairo-xcb
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(${APP_NAME} SYSTEM
|
target_include_directories(${APP_NAME} SYSTEM
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "core/backend.h"
|
#include "core/backend.h"
|
||||||
|
|
||||||
|
#include <cairo-xcb.h>
|
||||||
|
#include <cairo.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.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->windows);
|
||||||
p_delete(&result);
|
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};
|
||||||
|
}
|
||||||
|
|||||||
@@ -405,3 +405,49 @@ void window_grab_keys(
|
|||||||
p_delete(&keycodes);
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -104,3 +104,17 @@ void window_grab_keys(
|
|||||||
const key_bind_t *keys,
|
const key_bind_t *keys,
|
||||||
size_t count
|
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);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cairo.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "core/event.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);
|
backend_scan_result_t *backend_scan_windows(backend_t *backend);
|
||||||
void backend_scan_result_destroy(backend_scan_result_t *result);
|
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
|
||||||
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user