处理窗口销毁事件
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
@@ -78,10 +79,12 @@ typedef struct map_request_event_t {
|
|||||||
typedef struct unmap_notify_event_t {
|
typedef struct unmap_notify_event_t {
|
||||||
event_type_t type;
|
event_type_t type;
|
||||||
xcb_window_t window;
|
xcb_window_t window;
|
||||||
|
bool send_event;
|
||||||
} unmap_notify_event_t;
|
} unmap_notify_event_t;
|
||||||
|
|
||||||
typedef struct destroy_notify_event_t {
|
typedef struct destroy_notify_event_t {
|
||||||
event_type_t type;
|
event_type_t type;
|
||||||
|
xcb_window_t window;
|
||||||
} destroy_notify_event_t;
|
} destroy_notify_event_t;
|
||||||
|
|
||||||
typedef struct expose_event_t {
|
typedef struct expose_event_t {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ void map_window(xcb_window_t window);
|
|||||||
* @returns 返回窗口名字符串指针,使用完后记得使用 free 释放内存
|
* @returns 返回窗口名字符串指针,使用完后记得使用 free 释放内存
|
||||||
*/
|
*/
|
||||||
char *get_window_name(xcb_window_t window);
|
char *get_window_name(xcb_window_t window);
|
||||||
void init_window_event_mask(xcb_window_t window);
|
void set_window_event_mask(xcb_window_t window, bool clear);
|
||||||
void change_window_border_color(xcb_window_t window, uint32_t argb);
|
void change_window_border_color(xcb_window_t window, uint32_t argb);
|
||||||
void focus_window(xcb_window_t window);
|
void focus_window(xcb_window_t window);
|
||||||
|
|
||||||
@@ -112,5 +112,6 @@ typedef enum wm_state_t {
|
|||||||
} wm_state_t;
|
} wm_state_t;
|
||||||
int32_t get_window_state(xcb_window_t window);
|
int32_t get_window_state(xcb_window_t window);
|
||||||
void set_window_state(xcb_window_t window, wm_state_t state);
|
void set_window_state(xcb_window_t window, wm_state_t state);
|
||||||
|
void set_window_list(xcb_window_t *list, uint32_t length);
|
||||||
|
|
||||||
bool get_pointer_position(int32_t *x, int32_t *y);
|
bool get_pointer_position(int32_t *x, int32_t *y);
|
||||||
|
|||||||
51
src/main.c
51
src/main.c
@@ -39,11 +39,13 @@ static void key_press(key_press_event_t *event);
|
|||||||
static void configure_request(configure_request_event_t *event);
|
static void configure_request(configure_request_event_t *event);
|
||||||
static void map_request(map_request_event_t *event);
|
static void map_request(map_request_event_t *event);
|
||||||
static void unmap_notify(unmap_notify_event_t *event);
|
static void unmap_notify(unmap_notify_event_t *event);
|
||||||
|
static void destroy_notify(destroy_notify_event_t *event);
|
||||||
static void motion_notify(motion_notify_event_t *event);
|
static void motion_notify(motion_notify_event_t *event);
|
||||||
static void enter_notify(enter_notify_event_t *event);
|
static void enter_notify(enter_notify_event_t *event);
|
||||||
static void focus_in(focus_in_event_t *event);
|
static void focus_in(focus_in_event_t *event);
|
||||||
static void manage_window(xcb_window_t window);
|
static void manage_window(xcb_window_t window);
|
||||||
static void unmanage_client(client_t *client);
|
static void unmanage_client(client_t *client, bool destroyed);
|
||||||
|
static void update_client_list(void);
|
||||||
static void update_client_name(client_t *client);
|
static void update_client_name(client_t *client);
|
||||||
static void apply_rules(client_t *client);
|
static void apply_rules(client_t *client);
|
||||||
static uint32_t get_tags_mask_of_monitor(monitor_t *monitor);
|
static uint32_t get_tags_mask_of_monitor(monitor_t *monitor);
|
||||||
@@ -465,6 +467,7 @@ void xcb_event_handler(generic_event_t *event, void *user_data) {
|
|||||||
EVENT(EVENT_TYPE_CONFIGURE_REQUEST, configure_request);
|
EVENT(EVENT_TYPE_CONFIGURE_REQUEST, configure_request);
|
||||||
EVENT(EVENT_TYPE_MAP_REQUEST, map_request);
|
EVENT(EVENT_TYPE_MAP_REQUEST, map_request);
|
||||||
EVENT(EVENT_TYPE_UNMAP_NOTIFY, unmap_notify);
|
EVENT(EVENT_TYPE_UNMAP_NOTIFY, unmap_notify);
|
||||||
|
EVENT(EVENT_TYPE_DESTROY_NOTIFY, destroy_notify);
|
||||||
EVENT(EVENT_TYPE_MOTION_NOTIFY, motion_notify);
|
EVENT(EVENT_TYPE_MOTION_NOTIFY, motion_notify);
|
||||||
EVENT(EVENT_TYPE_ENTER_NOTIFY, enter_notify);
|
EVENT(EVENT_TYPE_ENTER_NOTIFY, enter_notify);
|
||||||
EVENT(EVENT_TYPE_FOCUS_IN, focus_in);
|
EVENT(EVENT_TYPE_FOCUS_IN, focus_in);
|
||||||
@@ -512,10 +515,19 @@ void map_request(map_request_event_t *event) {
|
|||||||
void unmap_notify(unmap_notify_event_t *event) {
|
void unmap_notify(unmap_notify_event_t *event) {
|
||||||
client_t *c = get_client_of_window(event->window);
|
client_t *c = get_client_of_window(event->window);
|
||||||
if (c) {
|
if (c) {
|
||||||
unmanage_client(c);
|
if (event->send_event) {
|
||||||
|
set_window_state(event->window, wm_state_withdrawn);
|
||||||
|
} else {
|
||||||
|
unmanage_client(c, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void destroy_notify(destroy_notify_event_t *event) {
|
||||||
|
client_t *c = get_client_of_window(event->window);
|
||||||
|
if (c) unmanage_client(c, true);
|
||||||
|
}
|
||||||
|
|
||||||
void motion_notify(motion_notify_event_t *event) {
|
void motion_notify(motion_notify_event_t *event) {
|
||||||
logger("motion: window: 0x%x, root: 0x%x\n", event->window, event->root);
|
logger("motion: window: 0x%x, root: 0x%x\n", event->window, event->root);
|
||||||
logger("x: %d, y: %d, root_x: %d, root_y: %d\n", event->x, event->y,
|
logger("x: %d, y: %d, root_x: %d, root_y: %d\n", event->x, event->y,
|
||||||
@@ -586,7 +598,7 @@ void manage_window(xcb_window_t window) {
|
|||||||
|
|
||||||
attach_client(c);
|
attach_client(c);
|
||||||
attach_stack_client(c);
|
attach_stack_client(c);
|
||||||
init_window_event_mask(window);
|
set_window_event_mask(window, false);
|
||||||
change_window_border_color(window, color_set->border_color.argb);
|
change_window_border_color(window, color_set->border_color.argb);
|
||||||
if (c->monitor == current_monitor) {
|
if (c->monitor == current_monitor) {
|
||||||
unfocus(current_monitor->selected_client, false);
|
unfocus(current_monitor->selected_client, false);
|
||||||
@@ -596,14 +608,41 @@ void manage_window(xcb_window_t window) {
|
|||||||
focus(NULL);
|
focus(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unmanage_client(client_t *client) {
|
void unmanage_client(client_t *client, bool destroyed) {
|
||||||
monitor_t *monitor = client->monitor;
|
monitor_t *monitor = client->monitor;
|
||||||
|
|
||||||
detach_client(client);
|
detach_client(client);
|
||||||
detach_stack_client(client);
|
detach_stack_client(client);
|
||||||
|
if (!destroyed) {
|
||||||
|
set_window_event_mask(client->window, true);
|
||||||
|
configure_window(client->window, client->x, client->y, client->width,
|
||||||
|
client->height, client->old_border_width);
|
||||||
|
set_window_state(client->window, wm_state_withdrawn);
|
||||||
|
flush_xcb_connection();
|
||||||
|
}
|
||||||
free(client);
|
free(client);
|
||||||
|
focus(NULL);
|
||||||
|
update_client_list();
|
||||||
arrange(monitor);
|
arrange(monitor);
|
||||||
flush_xcb_connection();
|
}
|
||||||
|
|
||||||
|
void update_client_list(void) {
|
||||||
|
uint32_t length = 0;
|
||||||
|
for (monitor_t *m = monitors; m; m = m->next) {
|
||||||
|
for (client_t *c = m->clients; c; c = c->next) length++;
|
||||||
|
}
|
||||||
|
if (!length) {
|
||||||
|
set_window_list(NULL, length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_window_t *list = ecalloc(length, sizeof(xcb_window_t));
|
||||||
|
uint32_t i = 0;
|
||||||
|
for (monitor_t *m = monitors; m; m = m->next) {
|
||||||
|
for (client_t *c = m->clients; c; c = c->next) list[i++] = c->window;
|
||||||
|
}
|
||||||
|
set_window_list(list, length);
|
||||||
|
free(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_client_name(client_t *client) {
|
void update_client_name(client_t *client) {
|
||||||
@@ -842,7 +881,7 @@ void cleanup(void) {
|
|||||||
while (m) {
|
while (m) {
|
||||||
while (c) {
|
while (c) {
|
||||||
client_t *tc = c->next;
|
client_t *tc = c->next;
|
||||||
free(c);
|
unmanage_client(c, false);
|
||||||
c = tc;
|
c = tc;
|
||||||
}
|
}
|
||||||
monitor_t *next_monitor = m->next;
|
monitor_t *next_monitor = m->next;
|
||||||
|
|||||||
@@ -65,10 +65,14 @@ static void convert_event(xcb_generic_event_t *xcb_event,
|
|||||||
xcb_unmap_notify_event_t *ev = (xcb_unmap_notify_event_t *)xcb_event;
|
xcb_unmap_notify_event_t *ev = (xcb_unmap_notify_event_t *)xcb_event;
|
||||||
event->unmap_notify.type = EVENT_TYPE_UNMAP_NOTIFY;
|
event->unmap_notify.type = EVENT_TYPE_UNMAP_NOTIFY;
|
||||||
event->unmap_notify.window = ev->window;
|
event->unmap_notify.window = ev->window;
|
||||||
|
event->unmap_notify.send_event = XCB_EVENT_SENT(ev);
|
||||||
} break;
|
} break;
|
||||||
case XCB_DESTROY_NOTIFY:
|
case XCB_DESTROY_NOTIFY: {
|
||||||
event->type = EVENT_TYPE_DESTROY_NOTIFY;
|
xcb_destroy_notify_event_t *ev = (xcb_destroy_notify_event_t *)xcb_event;
|
||||||
|
event->destroy_notify.type = EVENT_TYPE_DESTROY_NOTIFY;
|
||||||
|
event->destroy_notify.window = ev->window;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case XCB_EXPOSE:
|
case XCB_EXPOSE:
|
||||||
event->type = EVENT_TYPE_EXPOSE;
|
event->type = EVENT_TYPE_EXPOSE;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -274,13 +274,14 @@ char *get_window_name(xcb_window_t window) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_window_event_mask(xcb_window_t window) {
|
void set_window_event_mask(xcb_window_t window, bool clear) {
|
||||||
xcb_cw_t change_mask = XCB_CW_EVENT_MASK;
|
xcb_cw_t change_mask = XCB_CW_EVENT_MASK;
|
||||||
xcb_params_cw_t params = {
|
uint32_t event_mask = clear ? XCB_EVENT_MASK_NO_EVENT
|
||||||
.event_mask = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE |
|
: XCB_EVENT_MASK_ENTER_WINDOW |
|
||||||
XCB_EVENT_MASK_PROPERTY_CHANGE |
|
XCB_EVENT_MASK_FOCUS_CHANGE |
|
||||||
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY,
|
XCB_EVENT_MASK_PROPERTY_CHANGE |
|
||||||
};
|
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
|
||||||
|
xcb_params_cw_t params = {.event_mask = event_mask};
|
||||||
xcb_aux_change_window_attributes(conn, window, change_mask, ¶ms);
|
xcb_aux_change_window_attributes(conn, window, change_mask, ¶ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xcb_ewmh.h>
|
||||||
#include <xcb/xcb_icccm.h>
|
#include <xcb/xcb_icccm.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
@@ -149,3 +150,14 @@ void set_window_state(xcb_window_t window, wm_state_t state) {
|
|||||||
}
|
}
|
||||||
xcb_icccm_set_wm_hints(conn, window, &hints);
|
xcb_icccm_set_wm_hints(conn, window, &hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_window_list(xcb_window_t *list, uint32_t length) {
|
||||||
|
int screen_nbr = 0;
|
||||||
|
for (int i = 0; i < ewmh->nb_screens; i++) {
|
||||||
|
if (screen == ewmh->screens[i]) {
|
||||||
|
screen_nbr = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xcb_ewmh_set_client_list(ewmh, screen_nbr, length, list);
|
||||||
|
}
|
||||||
|
|||||||
@@ -184,10 +184,11 @@ window_list_t *scan_window_list(void) {
|
|||||||
|
|
||||||
xcb_window_t *list = xcb_query_tree_children(tree_reply);
|
xcb_window_t *list = xcb_query_tree_children(tree_reply);
|
||||||
int len = xcb_query_tree_children_length(tree_reply);
|
int len = xcb_query_tree_children_length(tree_reply);
|
||||||
|
if (!len) return NULL;
|
||||||
|
|
||||||
uint32_t normal_count = 0, transient_count = 0;
|
uint32_t normal_count = 0, transient_count = 0;
|
||||||
xcb_window_t normal_window_array[len];
|
xcb_window_t *normal_window_array = ecalloc(len, sizeof(xcb_window_t));
|
||||||
xcb_window_t transient_window_array[len];
|
xcb_window_t *transient_window_array = ecalloc(len, sizeof(xcb_window_t));
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
xcb_window_t window = list[i];
|
xcb_window_t window = list[i];
|
||||||
|
|
||||||
@@ -214,25 +215,12 @@ window_list_t *scan_window_list(void) {
|
|||||||
}
|
}
|
||||||
free(tree_reply);
|
free(tree_reply);
|
||||||
|
|
||||||
if ((!normal_count) && (!transient_count)) return NULL;
|
|
||||||
|
|
||||||
window_list_t *r = ecalloc(1, sizeof(window_list_t));
|
window_list_t *r = ecalloc(1, sizeof(window_list_t));
|
||||||
|
r->normal_list = normal_window_array;
|
||||||
|
r->transient_list = transient_window_array;
|
||||||
r->normal_count = normal_count;
|
r->normal_count = normal_count;
|
||||||
r->transient_count = transient_count;
|
r->transient_count = transient_count;
|
||||||
|
|
||||||
if (normal_count) {
|
|
||||||
r->normal_list = ecalloc(normal_count, sizeof(xcb_window_t));
|
|
||||||
for (uint32_t i = 0; i < normal_count; i++) {
|
|
||||||
r->normal_list[i] = normal_window_array[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (transient_count) {
|
|
||||||
r->transient_list = ecalloc(transient_count, sizeof(xcb_window_t));
|
|
||||||
for (uint32_t i = 0; i < transient_count; i++) {
|
|
||||||
r->transient_list[i] = transient_window_array[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user