完善 ewmh 扩展初始化

This commit is contained in:
2025-08-04 14:28:38 +08:00
parent 801124a8a2
commit 645d6594b8
6 changed files with 84 additions and 4 deletions

View File

@@ -39,3 +39,10 @@ target_include_directories(${APP_NAME} SYSTEM PUBLIC ${XCB_INCLUDE_DIRS})
add_subdirectory(xcb) add_subdirectory(xcb)
target_link_libraries(${APP_NAME} ${LIB_XCB_NAME}) target_link_libraries(${APP_NAME} ${LIB_XCB_NAME})
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/app.h.in"
"${CMAKE_BINARY_DIR}/app.h"
@ONLY
)
target_include_directories(${APP_NAME} PRIVATE ${CMAKE_BINARY_DIR})

3
src/app.h.in Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
#define APP_NAME "@APP_NAME@"

View File

@@ -1,9 +1,12 @@
set(LIB_XCB "zswm-xcb") set(LIB_XCB "zswm-xcb")
set(LIB_XCB_NAME ${LIB_XCB} PARENT_SCOPE) set(LIB_XCB_NAME ${LIB_XCB} PARENT_SCOPE)
add_library(${LIB_XCB} STATIC xcb.c) add_library(${LIB_XCB} STATIC xcb.c window.c)
target_include_directories(${LIB_XCB} SYSTEM PUBLIC ${XCB_INCLUDE_DIRS}) target_include_directories(${LIB_XCB} SYSTEM PUBLIC ${XCB_INCLUDE_DIRS})
target_include_directories(${LIB_XCB} PUBLIC "${CMAKE_SOURCE_DIR}/include") target_include_directories(${LIB_XCB} PUBLIC
"${CMAKE_SOURCE_DIR}/include"
"${CMAKE_BINARY_DIR}"
)
target_link_libraries(${LIB_XCB} ${XCB_LIBRARIES}) target_link_libraries(${LIB_XCB} ${XCB_LIBRARIES})

26
src/xcb/window.c Normal file
View File

@@ -0,0 +1,26 @@
#include "window.h"
#include <stdlib.h>
#include <string.h>
#include <xcb/xcb_icccm.h>
#include "xcb-private.h"
void set_window_class_instance(xcb_window_t window, const char *class,
const char *instance) {
size_t class_length = strlen(class) + 1;
size_t instance_length = strlen(instance) + 1;
size_t length = class_length + instance_length;
char *str = malloc(length * sizeof(char));
for (size_t i = 0; i < length; i++) {
if (i < class_length) {
str[i] = class[i];
} else {
str[i] = instance[i - class_length];
}
}
xcb_icccm_set_wm_class(conn, window, length, str);
free(str);
}

6
src/xcb/window.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
#include <xcb/xproto.h>
void set_window_class_instance(xcb_window_t window, const char *class,
const char *instance);

View File

@@ -10,9 +10,12 @@
#include <xcb/xcb_ewmh.h> #include <xcb/xcb_ewmh.h>
#include <xcb/xcb_icccm.h> #include <xcb/xcb_icccm.h>
#include <xcb/xinerama.h> #include <xcb/xinerama.h>
#include <xcb/xinput.h>
#include <xcb/xproto.h> #include <xcb/xproto.h>
#include "app.h"
#include "utils.h" #include "utils.h"
#include "window.h"
#include "xcb-private.h" #include "xcb-private.h"
xcb_connection_t *conn = NULL; xcb_connection_t *conn = NULL;
@@ -122,18 +125,50 @@ monitor_rect_t *detect_monitor_rect(void) {
} }
static xcb_ewmh_connection_t *ewmh = NULL; static xcb_ewmh_connection_t *ewmh = NULL;
static bool ewmh_init_failed = false;
static xcb_window_t wm_check_window = XCB_NONE;
static void init_ewmh_extension(void) { static void init_ewmh_extension(void) {
if (ewmh) return; if (ewmh || ewmh_init_failed) return;
ewmh = ecalloc(1, sizeof(xcb_ewmh_connection_t)); ewmh = ecalloc(1, sizeof(xcb_ewmh_connection_t));
xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(conn, ewmh); xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(conn, ewmh);
if (!xcb_ewmh_init_atoms_replies(ewmh, cookie, NULL)) { if (!xcb_ewmh_init_atoms_replies(ewmh, cookie, NULL)) {
free(ewmh); free(ewmh);
ewmh = NULL; ewmh = NULL;
ewmh_init_failed = true;
return; return;
} }
screen = ewmh->screens[ewmh->nb_screens - 1]; wm_check_window = xcb_generate_id(conn);
xcb_create_window(conn, XCB_COPY_FROM_PARENT, wm_check_window, screen->root,
0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
screen->root_visual, XCB_NONE, NULL);
const char *class = APP_NAME "_wm_check";
set_window_class_instance(wm_check_window, class, class);
xcb_ewmh_set_wm_name(ewmh, wm_check_window, strlen(APP_NAME), APP_NAME);
xcb_ewmh_set_supporting_wm_check(ewmh, screen->root, wm_check_window);
xcb_ewmh_set_supporting_wm_check(ewmh, wm_check_window, wm_check_window);
uint8_t mode = XCB_PROP_MODE_REPLACE;
uint8_t format = XCB_INPUT_PROPERTY_FORMAT_32_BITS;
xcb_atom_t atom = XCB_ATOM_ATOM;
const xcb_atom_t state[] = {ewmh->_NET_WM_STATE_STICKY};
const xcb_atom_t supported[] = {
ewmh->_NET_ACTIVE_WINDOW,
ewmh->_NET_SUPPORTED,
ewmh->_NET_WM_NAME,
ewmh->_NET_WM_STATE,
ewmh->_NET_SUPPORTING_WM_CHECK,
ewmh->_NET_WM_STATE_FULLSCREEN,
ewmh->_NET_WM_WINDOW_TYPE,
ewmh->_NET_WM_WINDOW_TYPE_DIALOG,
ewmh->_NET_CLIENT_LIST,
};
xcb_change_property(conn, mode, wm_check_window, ewmh->_NET_WM_STATE, atom,
format, LENGTH(state), state);
xcb_change_property(conn, mode, screen->root, ewmh->_NET_SUPPORTED, atom,
format, LENGTH(supported), supported);
xcb_delete_property(conn, screen->root, ewmh->_NET_CLIENT_LIST);
} }
/** /**