处理 property_notify 事件

This commit is contained in:
2025-08-24 12:44:15 +08:00
parent 165dd0733c
commit 8f892633cc
5 changed files with 63 additions and 14 deletions

View File

@@ -2,7 +2,6 @@
#include <stdbool.h>
#include <stdint.h>
#include <xcb/xproto.h>
#include "types.h"
@@ -115,8 +114,15 @@ typedef struct focus_in_event_t {
xcb_window_t window;
} focus_in_event_t;
typedef enum property_state_t {
property_new_value = 0,
property_delete = 1
} property_state_t;
typedef struct property_notify_event_t {
event_type_t type;
xcb_window_t window;
uint32_t xcb_atom;
property_state_t state;
} property_notify_event_t;
typedef struct client_message_event_t {

View File

@@ -103,7 +103,9 @@ typedef enum atom_t {
atom_wm_protocols,
atom_wm_delete,
atom_wm_take_focus,
atom_net_wm_name,
} atom_t;
xcb_atom_t get_xcb_atom(atom_t atom);
bool send_event(xcb_window_t window, atom_t atom);
typedef enum wm_state_t {
wm_state_withdrawn = 0,

View File

@@ -10,6 +10,7 @@
#include <string.h>
#include <unistd.h>
#include <wordexp.h>
#include <xcb/xproto.h>
#include "action.h"
#include "config.h"
@@ -44,6 +45,7 @@ static void expose(expose_event_t *event);
static void motion_notify(motion_notify_event_t *event);
static void enter_notify(enter_notify_event_t *event);
static void focus_in(focus_in_event_t *event);
static void property_notify(property_notify_event_t *event);
static void manage_window(xcb_window_t window);
static void unmanage_client(client_t *client, bool destroyed);
static void update_client_list(void);
@@ -473,6 +475,7 @@ void xcb_event_handler(generic_event_t *event, void *user_data) {
EVENT(EVENT_TYPE_MOTION_NOTIFY, motion_notify);
EVENT(EVENT_TYPE_ENTER_NOTIFY, enter_notify);
EVENT(EVENT_TYPE_FOCUS_IN, focus_in);
EVENT(EVENT_TYPE_PROPERTY_NOTIFY, property_notify);
#undef EVENT
@@ -579,6 +582,32 @@ void focus_in(focus_in_event_t *event) {
}
}
void property_notify(property_notify_event_t *event) {
if (event->state == property_delete) return;
client_t *c = get_client_of_window(event->window);
if (!c) return;
switch (event->xcb_atom) {
case XCB_ATOM_WM_TRANSIENT_FOR: {
xcb_window_t transient_for;
if (!c->floating &&
((transient_for = get_transient_window_for(event->window)) !=
WINDOW_NONE) &&
(c->floating = (get_client_of_window(transient_for) != NULL))) {
arrange(c->monitor);
}
break;
}
default:
break;
}
if (event->xcb_atom == XCB_ATOM_WM_NAME ||
event->xcb_atom == get_xcb_atom(atom_net_wm_name)) {
update_client_name(c);
if (c->tags & c->monitor->selected_tags) draw_monitor_bar(c->monitor);
}
}
void manage_window(xcb_window_t window) {
window_geometry_t *geometry = get_window_geometry(window);
client_t *c = ecalloc(1, sizeof(client_t));
@@ -874,17 +903,6 @@ gboolean handle_xcb_event(GIOChannel *channel, GIOCondition condition,
}
void cleanup(void) {
clean_pango_context();
free_wallpaper_config(wallpaper_config);
wallpaper_config = NULL;
free(color_set);
color_set = NULL;
free(font_family);
font_family = NULL;
monitor_t *m = monitors;
client_t *c = m->clients;
while (m) {
@@ -902,6 +920,17 @@ void cleanup(void) {
}
monitors = NULL;
clean_pango_context();
free_wallpaper_config(wallpaper_config);
wallpaper_config = NULL;
free(color_set);
color_set = NULL;
free(font_family);
font_family = NULL;
destroy_event_adapter(adapter);
adapter = NULL;

View File

@@ -104,9 +104,15 @@ static void convert_event(xcb_generic_event_t *xcb_event,
event->focus_in.type = EVENT_TYPE_FOCUS_IN;
event->focus_in.window = ev->event;
} break;
case XCB_PROPERTY_NOTIFY:
event->type = EVENT_TYPE_PROPERTY_NOTIFY;
case XCB_PROPERTY_NOTIFY: {
xcb_property_notify_event_t *ev =
(xcb_property_notify_event_t *)xcb_event;
event->property_notify.type = EVENT_TYPE_PROPERTY_NOTIFY;
event->property_notify.window = ev->window;
event->property_notify.xcb_atom = ev->atom;
event->property_notify.state = ev->state;
break;
}
case XCB_CLIENT_MESSAGE:
event->type = EVENT_TYPE_CLIENT_MESSAGE;
break;

View File

@@ -25,6 +25,7 @@ static atom_map_t atom_map[] = {
{.atom = atom_wm_protocols, .name = "WM_PROTOCOLS"},
{.atom = atom_wm_delete, .name = "WM_DELETE_WINDOW"},
{.atom = atom_wm_take_focus, .name = "WM_TAKE_FOCUS"},
{.atom = atom_net_wm_name, .name = "_NET_WM_NAME"},
};
void init_icccm_extension(void) {
@@ -97,6 +98,11 @@ void clean_ewmh_extension(void) {
}
}
xcb_atom_t get_xcb_atom(atom_t atom) {
if (atom < 0 || atom >= LENGTH(atom_map)) return XCB_ATOM_NONE;
return atom_map[atom].xcb_atom;
}
bool send_event(xcb_window_t window, atom_t atom) {
if (atom < 0 || atom >= LENGTH(atom_map)) return false;