feat(backend): 添加光标支持
This commit is contained in:
@@ -26,6 +26,7 @@ project(${APP_NAME}
|
|||||||
add_executable(${APP_NAME}
|
add_executable(${APP_NAME}
|
||||||
${SOURCE_DIR}/backend/output_utils.c
|
${SOURCE_DIR}/backend/output_utils.c
|
||||||
${SOURCE_DIR}/backend/x11/backend.c
|
${SOURCE_DIR}/backend/x11/backend.c
|
||||||
|
${SOURCE_DIR}/backend/x11/cursor.c
|
||||||
${SOURCE_DIR}/backend/x11/event.c
|
${SOURCE_DIR}/backend/x11/event.c
|
||||||
${SOURCE_DIR}/backend/x11/window.c
|
${SOURCE_DIR}/backend/x11/window.c
|
||||||
|
|
||||||
@@ -76,6 +77,7 @@ find_package(PkgConfig REQUIRED)
|
|||||||
pkg_check_modules(deps REQUIRED
|
pkg_check_modules(deps REQUIRED
|
||||||
xcb
|
xcb
|
||||||
xcb-aux
|
xcb-aux
|
||||||
|
xcb-cursor
|
||||||
xcb-icccm
|
xcb-icccm
|
||||||
xcb-keysyms
|
xcb-keysyms
|
||||||
xcb-randr
|
xcb-randr
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
#include "backend/output_utils.h"
|
#include "backend/output_utils.h"
|
||||||
|
#include "backend/x11/cursor.h"
|
||||||
#include "backend/x11/window.h"
|
#include "backend/x11/window.h"
|
||||||
#include "base/app.h"
|
#include "base/app.h"
|
||||||
#include "base/array.h"
|
#include "base/array.h"
|
||||||
@@ -184,10 +185,13 @@ backend_t *backend_create(const char *display_name) {
|
|||||||
|
|
||||||
backend->key_symbols = xcb_key_symbols_alloc(conn);
|
backend->key_symbols = xcb_key_symbols_alloc(conn);
|
||||||
|
|
||||||
|
cursor_init(backend);
|
||||||
atoms_init(backend);
|
atoms_init(backend);
|
||||||
create_wm_check_window(backend);
|
create_wm_check_window(backend);
|
||||||
create_no_focus_window(backend);
|
create_no_focus_window(backend);
|
||||||
|
|
||||||
|
window_change_cursor(backend, root, ZDWM_CURSOR_NORMAL);
|
||||||
|
|
||||||
return backend;
|
return backend;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,6 +208,8 @@ void backend_destroy(backend_t *backend) {
|
|||||||
xcb_key_symbols_free(backend->key_symbols);
|
xcb_key_symbols_free(backend->key_symbols);
|
||||||
backend->key_symbols = nullptr;
|
backend->key_symbols = nullptr;
|
||||||
|
|
||||||
|
cursor_cleanup(backend);
|
||||||
|
|
||||||
xcb_disconnect(backend->conn);
|
xcb_disconnect(backend->conn);
|
||||||
backend->conn = nullptr;
|
backend->conn = nullptr;
|
||||||
free(backend);
|
free(backend);
|
||||||
|
|||||||
51
src/backend/x11/cursor.c
Normal file
51
src/backend/x11/cursor.c
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
#include <xcb/xcb_cursor.h>
|
||||||
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
|
#include "base/macros.h"
|
||||||
|
#include "base/memory.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
static const char *const cursor_name_map[] = {
|
||||||
|
[ZDWM_CURSOR_NORMAL] = "left_ptr",
|
||||||
|
[ZDWM_CURSOR_MOVE] = "fleur",
|
||||||
|
[ZDWM_CURSOR_RESIZE] = "bottom_right_corner",
|
||||||
|
};
|
||||||
|
|
||||||
|
static xcb_cursor_context_t *get_xcb_cursor_context(backend_t *backend) {
|
||||||
|
if (backend->cursor_context) return backend->cursor_context;
|
||||||
|
|
||||||
|
auto conn = backend->conn;
|
||||||
|
auto screen = backend->screen;
|
||||||
|
if (xcb_cursor_context_new(conn, screen, &backend->cursor_context) == 0) {
|
||||||
|
return backend->cursor_context;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cursor_init(backend_t *backend) {
|
||||||
|
auto ctx = get_xcb_cursor_context(backend);
|
||||||
|
if (!ctx) return;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < countof(backend->cursors); ++i) {
|
||||||
|
auto cursor_name = cursor_name_map[i];
|
||||||
|
backend->cursors[i] = xcb_cursor_load_cursor(ctx, cursor_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cursor_cleanup(backend_t *backend) {
|
||||||
|
constexpr size_t count = countof(backend->cursors);
|
||||||
|
for (size_t i = 0; i < count; ++i) {
|
||||||
|
xcb_free_cursor(backend->conn, backend->cursors[i]);
|
||||||
|
}
|
||||||
|
p_clear(backend->cursors, count);
|
||||||
|
xcb_cursor_context_free(backend->cursor_context);
|
||||||
|
backend->cursor_context = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_cursor_t cursor_get_xcb_cursor(backend_t *backend, cursor_t cursor) {
|
||||||
|
if (backend->cursor_context == nullptr) return XCB_CURSOR_NONE;
|
||||||
|
|
||||||
|
return backend->cursors[cursor];
|
||||||
|
}
|
||||||
9
src/backend/x11/cursor.h
Normal file
9
src/backend/x11/cursor.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
void cursor_init(backend_t *backend);
|
||||||
|
void cursor_cleanup(backend_t *backend);
|
||||||
|
xcb_cursor_t cursor_get_xcb_cursor(backend_t *backend, cursor_t cursor);
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xcb_cursor.h>
|
||||||
#include <xcb/xcb_keysyms.h>
|
#include <xcb/xcb_keysyms.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
@@ -78,7 +79,14 @@ typedef struct window_configure_list_t {
|
|||||||
size_t capacity;
|
size_t capacity;
|
||||||
} window_configure_list_t;
|
} window_configure_list_t;
|
||||||
|
|
||||||
struct backend_t {
|
typedef enum cursor_t {
|
||||||
|
ZDWM_CURSOR_NORMAL,
|
||||||
|
ZDWM_CURSOR_MOVE,
|
||||||
|
ZDWM_CURSOR_RESIZE,
|
||||||
|
ZDWM_CURSOR_COUNT,
|
||||||
|
} cursor_t;
|
||||||
|
|
||||||
|
typedef struct backend_t {
|
||||||
xcb_key_symbols_t *key_symbols;
|
xcb_key_symbols_t *key_symbols;
|
||||||
xcb_connection_t *conn;
|
xcb_connection_t *conn;
|
||||||
xcb_screen_t *screen;
|
xcb_screen_t *screen;
|
||||||
@@ -94,11 +102,14 @@ struct backend_t {
|
|||||||
xcb_window_t focus_window;
|
xcb_window_t focus_window;
|
||||||
bool update_focus;
|
bool update_focus;
|
||||||
|
|
||||||
|
xcb_cursor_t cursors[ZDWM_CURSOR_COUNT];
|
||||||
|
xcb_cursor_context_t *cursor_context;
|
||||||
|
|
||||||
window_configure_list_t config_list;
|
window_configure_list_t config_list;
|
||||||
window_list_t unmap;
|
window_list_t unmap;
|
||||||
window_list_t map;
|
window_list_t map;
|
||||||
window_list_t kill;
|
window_list_t kill;
|
||||||
};
|
} backend_t;
|
||||||
|
|
||||||
bool populate_window_event(
|
bool populate_window_event(
|
||||||
struct backend_t *backend,
|
struct backend_t *backend,
|
||||||
|
|||||||
@@ -3,10 +3,12 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xcb_aux.h>
|
||||||
#include <xcb/xcb_icccm.h>
|
#include <xcb/xcb_icccm.h>
|
||||||
#include <xcb/xcb_keysyms.h>
|
#include <xcb/xcb_keysyms.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
|
#include "backend/x11/cursor.h"
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/backend.h"
|
#include "core/backend.h"
|
||||||
@@ -451,3 +453,13 @@ visual_t *window_get_visual(backend_t *backend, bool prefer_alpha) {
|
|||||||
|
|
||||||
return visual;
|
return visual;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void window_change_cursor(
|
||||||
|
backend_t *backend,
|
||||||
|
xcb_window_t window,
|
||||||
|
cursor_t cursor
|
||||||
|
) {
|
||||||
|
auto conn = backend->conn;
|
||||||
|
xcb_params_cw_t params = {.cursor = cursor_get_xcb_cursor(backend, cursor)};
|
||||||
|
xcb_aux_change_window_attributes(conn, window, XCB_CW_CURSOR, ¶ms);
|
||||||
|
}
|
||||||
|
|||||||
@@ -118,3 +118,9 @@ typedef struct visual_t {
|
|||||||
* @returns 返回的信息使用后记得使用 free 释放
|
* @returns 返回的信息使用后记得使用 free 释放
|
||||||
*/
|
*/
|
||||||
visual_t *window_get_visual(backend_t *backend, bool prefer_alpha);
|
visual_t *window_get_visual(backend_t *backend, bool prefer_alpha);
|
||||||
|
|
||||||
|
void window_change_cursor(
|
||||||
|
backend_t *backend,
|
||||||
|
xcb_window_t window,
|
||||||
|
cursor_t cursor
|
||||||
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user