Bug fix: Segfault when meeting FocusIn/Out from destoryed windows
I found compton segfaults sometimes when starting from .xinitrc. Debugging reveals my conky window was just reparented to a fvwm's frame window before compton picked up a FocusOut event on this conky window that has just been destroyed in the event queue. find_win() call in ev_focus_in/out() returned a NULL pointer. When it tried to use the pointer segfault happens. - Add extra check to ev_focus_in/out() to stop the segfault. - Reset window event mask on window reparenting to a non-root window to minimize wrong events. - More abstraction for determining window event mask.
This commit is contained in:
parent
18b3a96d0b
commit
271d894eae
|
@ -704,6 +704,21 @@ should_ignore(Display *dpy, unsigned long sequence) {
|
||||||
* Windows
|
* Windows
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
long determine_evmask(Display *dpy, Window wid, enum win_evmode_t mode) {
|
||||||
|
long evmask = NoEventMask;
|
||||||
|
|
||||||
|
if (WIN_EVMODE_FRAME == mode || find_win(dpy, wid)) {
|
||||||
|
evmask |= PropertyChangeMask;
|
||||||
|
if (track_focus)
|
||||||
|
evmask |= FocusChangeMask;
|
||||||
|
}
|
||||||
|
if (WIN_EVMODE_CLIENT == mode || find_client_win(dpy, wid)) {
|
||||||
|
evmask |= PropertyChangeMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
return evmask;
|
||||||
|
}
|
||||||
|
|
||||||
static win *
|
static win *
|
||||||
find_win(Display *dpy, Window id) {
|
find_win(Display *dpy, Window id) {
|
||||||
win *w;
|
win *w;
|
||||||
|
@ -1439,10 +1454,7 @@ map_win(Display *dpy, Window id,
|
||||||
/* select before reading the property
|
/* select before reading the property
|
||||||
so that no property changes are lost */
|
so that no property changes are lost */
|
||||||
if (!override_redirect) {
|
if (!override_redirect) {
|
||||||
long evmask = PropertyChangeMask;
|
XSelectInput(dpy, id, determine_evmask(dpy, id, WIN_EVMODE_FRAME));
|
||||||
if (track_focus)
|
|
||||||
evmask |= FocusChangeMask;
|
|
||||||
XSelectInput(dpy, id, evmask);
|
|
||||||
// Notify compton when the shape of a window changes
|
// Notify compton when the shape of a window changes
|
||||||
if (shape_exists) {
|
if (shape_exists) {
|
||||||
XShapeSelectInput(dpy, id, ShapeNotifyMask);
|
XShapeSelectInput(dpy, id, ShapeNotifyMask);
|
||||||
|
@ -1785,8 +1797,7 @@ add_win(Display *dpy, Window id, Window prev, Bool override_redirect) {
|
||||||
get_frame_extents(dpy, cw,
|
get_frame_extents(dpy, cw,
|
||||||
&new->left_width, &new->right_width,
|
&new->left_width, &new->right_width,
|
||||||
&new->top_width, &new->bottom_width);
|
&new->top_width, &new->bottom_width);
|
||||||
if (id != cw)
|
XSelectInput(dpy, cw, determine_evmask(dpy, id, WIN_EVMODE_CLIENT));
|
||||||
XSelectInput(dpy, cw, PropertyChangeMask);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2301,6 +2312,10 @@ inline static void
|
||||||
ev_focus_in(XFocusChangeEvent *ev) {
|
ev_focus_in(XFocusChangeEvent *ev) {
|
||||||
win *w = find_win(dpy, ev->window);
|
win *w = find_win(dpy, ev->window);
|
||||||
|
|
||||||
|
// To deal with events sent from windows just destroyed
|
||||||
|
if (!w)
|
||||||
|
return;
|
||||||
|
|
||||||
w->focused = True;
|
w->focused = True;
|
||||||
calc_opacity(dpy, w, False);
|
calc_opacity(dpy, w, False);
|
||||||
calc_dim(dpy, w);
|
calc_dim(dpy, w);
|
||||||
|
@ -2319,7 +2334,11 @@ ev_focus_out(XFocusChangeEvent *ev) {
|
||||||
|
|
||||||
win *w = find_win(dpy, ev->window);
|
win *w = find_win(dpy, ev->window);
|
||||||
|
|
||||||
|
// To deal with events sent from windows just destroyed
|
||||||
|
if (!w)
|
||||||
|
return;
|
||||||
w->focused = False;
|
w->focused = False;
|
||||||
|
|
||||||
calc_opacity(dpy, w, False);
|
calc_opacity(dpy, w, False);
|
||||||
calc_dim(dpy, w);
|
calc_dim(dpy, w);
|
||||||
}
|
}
|
||||||
|
@ -2358,6 +2377,9 @@ ev_reparent_notify(XReparentEvent *ev) {
|
||||||
add_win(dpy, ev->window, 0, ev->override_redirect);
|
add_win(dpy, ev->window, 0, ev->override_redirect);
|
||||||
} else {
|
} else {
|
||||||
destroy_win(dpy, ev->window, True);
|
destroy_win(dpy, ev->window, True);
|
||||||
|
// Reset event mask in case something wrong happens
|
||||||
|
XSelectInput(dpy, ev->window,
|
||||||
|
determine_evmask(dpy, ev->window, WIN_EVMODE_UNKNOWN));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue