Ignore X11 errors caused by ReparentWindow / ChangeProperty on already destroyed windows
These errors can happen because a DestroyWindow request by a client will trigger an UnmapNotify, then a DestroyNotify. We cannot distinguish this UnmapNotify from an UnmapNotify not followed by a DestroyNotify, so we just try to send the ReparentWindow / ChangeProperty and ignore the errors, if any.
This commit is contained in:
parent
48f5166daf
commit
05e39c1c48
|
@ -15,8 +15,22 @@
|
||||||
|
|
||||||
extern int randr_base;
|
extern int randr_base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the given sequence to the list of events which are ignored.
|
||||||
|
* If this ignore should only affect a specific response_type, pass
|
||||||
|
* response_type, otherwise, pass -1.
|
||||||
|
*
|
||||||
|
* Every ignored sequence number gets garbage collected after 5 seconds.
|
||||||
|
*
|
||||||
|
*/
|
||||||
void add_ignore_event(const int sequence, const int response_type);
|
void add_ignore_event(const int sequence, const int response_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given sequence is ignored and returns true if so.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool event_is_ignored(const int sequence, const int response_type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes an xcb_generic_event_t and calls the appropriate handler, based on the
|
* Takes an xcb_generic_event_t and calls the appropriate handler, based on the
|
||||||
* event type.
|
* event type.
|
||||||
|
|
|
@ -21,6 +21,14 @@ int randr_base = -1;
|
||||||
changing workspaces */
|
changing workspaces */
|
||||||
static SLIST_HEAD(ignore_head, Ignore_Event) ignore_events;
|
static SLIST_HEAD(ignore_head, Ignore_Event) ignore_events;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adds the given sequence to the list of events which are ignored.
|
||||||
|
* If this ignore should only affect a specific response_type, pass
|
||||||
|
* response_type, otherwise, pass -1.
|
||||||
|
*
|
||||||
|
* Every ignored sequence number gets garbage collected after 5 seconds.
|
||||||
|
*
|
||||||
|
*/
|
||||||
void add_ignore_event(const int sequence, const int response_type) {
|
void add_ignore_event(const int sequence, const int response_type) {
|
||||||
struct Ignore_Event *event = smalloc(sizeof(struct Ignore_Event));
|
struct Ignore_Event *event = smalloc(sizeof(struct Ignore_Event));
|
||||||
|
|
||||||
|
@ -35,7 +43,7 @@ void add_ignore_event(const int sequence, const int response_type) {
|
||||||
* Checks if the given sequence is ignored and returns true if so.
|
* Checks if the given sequence is ignored and returns true if so.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static bool event_is_ignored(const int sequence, const int response_type) {
|
bool event_is_ignored(const int sequence, const int response_type) {
|
||||||
struct Ignore_Event *event;
|
struct Ignore_Event *event;
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
for (event = SLIST_FIRST(&ignore_events); event != SLIST_END(&ignore_events);) {
|
for (event = SLIST_FIRST(&ignore_events); event != SLIST_END(&ignore_events);) {
|
||||||
|
@ -51,7 +59,7 @@ static bool event_is_ignored(const int sequence, const int response_type) {
|
||||||
if (event->sequence != sequence)
|
if (event->sequence != sequence)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (event->response_type != 0 &&
|
if (event->response_type != -1 &&
|
||||||
event->response_type != response_type)
|
event->response_type != response_type)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -286,7 +294,7 @@ static int handle_map_request(xcb_map_request_event_t *event) {
|
||||||
cookie = xcb_get_window_attributes_unchecked(conn, event->window);
|
cookie = xcb_get_window_attributes_unchecked(conn, event->window);
|
||||||
|
|
||||||
DLOG("window = 0x%08x, serial is %d.\n", event->window, event->sequence);
|
DLOG("window = 0x%08x, serial is %d.\n", event->window, event->sequence);
|
||||||
add_ignore_event(event->sequence, 0);
|
add_ignore_event(event->sequence, -1);
|
||||||
|
|
||||||
manage_window(event->window, cookie, false);
|
manage_window(event->window, cookie, false);
|
||||||
x_push_changes(croot);
|
x_push_changes(croot);
|
||||||
|
|
|
@ -70,7 +70,9 @@ static void xcb_check_cb(EV_P_ ev_check *w, int revents) {
|
||||||
|
|
||||||
while ((event = xcb_poll_for_event(conn)) != NULL) {
|
while ((event = xcb_poll_for_event(conn)) != NULL) {
|
||||||
if (event->response_type == 0) {
|
if (event->response_type == 0) {
|
||||||
ELOG("X11 Error received! sequence %x\n", event->sequence);
|
if (event_is_ignored(event->sequence, 0))
|
||||||
|
DLOG("Expected X11 Error received for sequence %x\n", event->sequence);
|
||||||
|
else ELOG("X11 Error received! sequence %x\n", event->sequence);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
16
src/tree.c
16
src/tree.c
|
@ -153,13 +153,23 @@ bool tree_close(Con *con, kill_window_t kill_window, bool dont_kill_parent) {
|
||||||
x_window_kill(con->window->id, kill_window);
|
x_window_kill(con->window->id, kill_window);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
xcb_void_cookie_t cookie;
|
||||||
/* un-parent the window */
|
/* un-parent the window */
|
||||||
xcb_reparent_window(conn, con->window->id, root, 0, 0);
|
cookie = xcb_reparent_window(conn, con->window->id, root, 0, 0);
|
||||||
|
|
||||||
|
/* Ignore X11 errors for the ReparentWindow request.
|
||||||
|
* X11 Errors are returned when the window was already destroyed */
|
||||||
|
add_ignore_event(cookie.sequence, 0);
|
||||||
|
|
||||||
/* We are no longer handling this window, thus set WM_STATE to
|
/* We are no longer handling this window, thus set WM_STATE to
|
||||||
* WM_STATE_WITHDRAWN (see ICCCM 4.1.3.1) */
|
* WM_STATE_WITHDRAWN (see ICCCM 4.1.3.1) */
|
||||||
long data[] = { XCB_ICCCM_WM_STATE_WITHDRAWN, XCB_NONE };
|
long data[] = { XCB_ICCCM_WM_STATE_WITHDRAWN, XCB_NONE };
|
||||||
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, con->window->id,
|
cookie = xcb_change_property(conn, XCB_PROP_MODE_REPLACE,
|
||||||
A_WM_STATE, A_WM_STATE, 32, 2, data);
|
con->window->id, A_WM_STATE, A_WM_STATE, 32, 2, data);
|
||||||
|
|
||||||
|
/* Ignore X11 errors for the ReparentWindow request.
|
||||||
|
* X11 Errors are returned when the window was already destroyed */
|
||||||
|
add_ignore_event(cookie.sequence, 0);
|
||||||
}
|
}
|
||||||
FREE(con->window->class_class);
|
FREE(con->window->class_class);
|
||||||
FREE(con->window->class_instance);
|
FREE(con->window->class_instance);
|
||||||
|
|
|
@ -328,7 +328,7 @@ void xcb_set_window_rect(xcb_connection_t *conn, xcb_window_t window, Rect r) {
|
||||||
XCB_CONFIG_WINDOW_HEIGHT,
|
XCB_CONFIG_WINDOW_HEIGHT,
|
||||||
&(r.x));
|
&(r.x));
|
||||||
/* ignore events which are generated because we configured a window */
|
/* ignore events which are generated because we configured a window */
|
||||||
add_ignore_event(cookie.sequence, 0);
|
add_ignore_event(cookie.sequence, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue