Compare commits

...

6 Commits

9 changed files with 87 additions and 15 deletions

View File

@@ -28,13 +28,14 @@ wm: $(TARGET_NAME)
DISPLAY=:3 $(TARGET)
debug: $(TARGET_NAME)
DISPLAY=:3 valgrind $(TARGET)
DISPLAY=:3 valgrind --leak-check=full $(TARGET)
prepare:
@cmake -S $(SRC_DIR) -B $(BUILD_DIR)
@cp $(BUILD_DIR)/compile_commands.json $(MAKEFILE_DIR)
build: prepare
${RM} -f $(TARGET)
@cmake --build $(BUILD_DIR)
@cp $(BUILD_DIR)/$(TARGET_NAME) $(TARGET)

21
TODO.org Normal file
View File

@@ -0,0 +1,21 @@
#+title: zswm 代办事项
* TODO 调整光标在每个 monitor 中最后停留位置的逻辑
因为在有些程序(如 Emacs 和 Firefox中移动鼠标不会触发 motion_notify 事件,
因此需调整记录每个 monitor 中光标最后停留位置的逻辑,不能将 motion_notify 事件作为唯一依赖。
可在切换屏幕时主动查询当前光标,将其位置记录到切换前的 monitor 中。
* TODO 处理鼠标点击 bar_window 事件
* TODO 处理鼠标移动窗口事件
* TODO 处理鼠标调整窗口大小事件
* TODO 调整 stack 顺序和焦点逻辑,总感觉现在的情况有 bug
* TODO 调整 stack 逻辑,让 bar_window 在最底部
* TODO 添加切换布局算法功能
* TODO 添加系统托盘显示

View File

@@ -12,6 +12,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# compile flags
add_compile_options(-g)
add_compile_options(-Wall)
# add_link_options(-fsanitize=address)
project(${APP_NAME}
VERSION 0.0.1

View File

@@ -40,8 +40,15 @@ typedef enum notify_detail_t {
notify_detail_none = 7,
} notify_detail_t;
typedef enum mapping_t {
MAPPING_MODIFIER = 0,
MAPPING_KEYBOARD = 1,
MAPPING_POINTER = 2
} mapping_t;
typedef struct mapping_notify_event_t {
event_type_t type;
mapping_t request;
} mapping_notify_event_t;
typedef struct key_press_event_t {
@@ -52,6 +59,10 @@ typedef struct key_press_event_t {
typedef struct button_press_event_t {
event_type_t type;
xcb_window_t window;
xcb_window_t root;
int32_t x, y, root_x, root_y;
uint32_t time; /* 时间戳单位ms */
} button_press_event_t;
typedef struct configure_request_event_t {

View File

@@ -135,6 +135,7 @@ typedef enum atom_t {
atom_zswm_client_info, /* 自定义属性,用于存储所在 monitor 和 tags */
} atom_t;
xcb_atom_t get_xcb_atom(atom_t atom);
char *get_xcb_atom_name(xcb_atom_t atom);
bool send_event(xcb_window_t window, atom_t atom);
typedef enum wm_state_t {
wm_state_withdrawn = 0,

View File

@@ -926,8 +926,10 @@ void focus_in(focus_in_event_t *event) {
}
void property_notify(property_notify_event_t *event) {
logger("window: 0x%x state: %u, atom: %u\n", event->window, event->state,
event->xcb_atom);
char *atom_name = get_xcb_atom_name(event->xcb_atom);
logger("window: 0x%x state: %u, atom: %u, atom name: %s\n", event->window,
event->state, event->xcb_atom, atom_name);
free(atom_name);
if (event->state == property_delete) return;
client_t *c = get_client_of_window(event->window);
@@ -956,6 +958,10 @@ void property_notify(property_notify_event_t *event) {
}
void client_message(client_message_event_t *event) {
char *atom_name = get_xcb_atom_name(event->message_type);
logger("client message: message type: %s\n", atom_name);
free(atom_name);
client_t *c = get_client_of_window(event->window);
if (!c) return;
@@ -1014,6 +1020,8 @@ void manage_window(xcb_window_t window) {
c->height = c->old_height = geometry->height;
c->old_border_width = geometry->border_width;
c->border_width = border_px;
free(geometry);
update_client_name(c);
logger("== manage window: 0x%x\n", window);

View File

@@ -18,11 +18,13 @@ struct event_adapter_t {
static void convert_event(xcb_generic_event_t *xcb_event,
generic_event_t *event) {
uint8_t event_type = XCB_EVENT_RESPONSE_TYPE(xcb_event);
const char *label = xcb_event_get_label(event_type);
switch (event_type) {
case XCB_MAPPING_NOTIFY:
event->type = EVENT_TYPE_MAPPING_NOTIFY;
case XCB_MAPPING_NOTIFY: {
xcb_mapping_notify_event_t *ev = (xcb_mapping_notify_event_t *)xcb_event;
event->mapping_notify.type = EVENT_TYPE_MAPPING_NOTIFY;
event->mapping_notify.request = ev->request;
break;
}
case XCB_KEY_PRESS: {
xcb_key_press_event_t *ev = (xcb_key_press_event_t *)xcb_event;
int col = ev->state & XCB_MOD_MASK_2 ? 1 : 0;
@@ -32,9 +34,18 @@ static void convert_event(xcb_generic_event_t *xcb_event,
event->key_press.modifiers = ev->state;
break;
}
case XCB_BUTTON_PRESS:
event->type = EVENT_TYPE_BUTTON_PRESS;
case XCB_BUTTON_PRESS: {
xcb_button_press_event_t *ev = (xcb_button_press_event_t *)xcb_event;
event->button_press.type = EVENT_TYPE_BUTTON_PRESS;
event->button_press.window = ev->event;
event->button_press.root = ev->root;
event->button_press.x = ev->event_x;
event->button_press.y = ev->event_y;
event->button_press.root_x = ev->root_x;
event->button_press.root_y = ev->root_y;
event->button_press.time = ev->time;
break;
}
case XCB_CONFIGURE_REQUEST: {
xcb_configure_request_event_t *ev =
(xcb_configure_request_event_t *)xcb_event;
@@ -66,7 +77,8 @@ static void convert_event(xcb_generic_event_t *xcb_event,
event->unmap_notify.type = EVENT_TYPE_UNMAP_NOTIFY;
event->unmap_notify.window = ev->window;
event->unmap_notify.send_event = XCB_EVENT_SENT(ev);
} break;
break;
}
case XCB_DESTROY_NOTIFY: {
xcb_destroy_notify_event_t *ev = (xcb_destroy_notify_event_t *)xcb_event;
event->destroy_notify.type = EVENT_TYPE_DESTROY_NOTIFY;
@@ -127,7 +139,8 @@ static void convert_event(xcb_generic_event_t *xcb_event,
event->type = -1;
return;
}
if (event->type != EVENT_TYPE_MOTION_NOTIFY) {
if (event->type) {
const char *label = xcb_event_get_label(event_type);
logger("========================== %s ==========================\n", label);
}
}

View File

@@ -288,11 +288,10 @@ char *get_window_name(xcb_window_t window) {
void set_window_event_mask(xcb_window_t window, bool clear) {
xcb_cw_t change_mask = XCB_CW_EVENT_MASK;
uint32_t event_mask = clear ? XCB_EVENT_MASK_NO_EVENT
: XCB_EVENT_MASK_ENTER_WINDOW |
XCB_EVENT_MASK_FOCUS_CHANGE |
XCB_EVENT_MASK_PROPERTY_CHANGE |
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
uint32_t init_event_mask =
XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE |
XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
uint32_t event_mask = clear ? XCB_EVENT_MASK_NO_EVENT : init_event_mask;
xcb_params_cw_t params = {.event_mask = event_mask};
xcb_aux_change_window_attributes(conn, window, change_mask, &params);
}

View File

@@ -111,6 +111,23 @@ xcb_atom_t get_xcb_atom(atom_t atom) {
return atom_map[atom].xcb_atom;
}
/**
* @brief 获取 xcb atom 名称
* @returns xcb atom 对应的名称,使用后记得用 free 释放
*/
char *get_xcb_atom_name(xcb_atom_t atom) {
xcb_get_atom_name_cookie_t cookie = xcb_get_atom_name(conn, atom);
xcb_get_atom_name_reply_t *reply =
xcb_get_atom_name_reply(conn, cookie, NULL);
int length = xcb_get_atom_name_name_length(reply);
char *name_buffer = ecalloc(1, length + 1);
const char *name = xcb_get_atom_name_name(reply);
strncpy(name_buffer, name, length);
free(reply);
return name_buffer;
}
bool send_event(xcb_window_t window, atom_t atom) {
if (atom < 0 || atom >= LENGTH(atom_map)) return false;