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
|
||||
*/
|
||||
|
||||
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 *
|
||||
find_win(Display *dpy, Window id) {
|
||||
win *w;
|
||||
|
@ -1439,10 +1454,7 @@ map_win(Display *dpy, Window id,
|
|||
/* select before reading the property
|
||||
so that no property changes are lost */
|
||||
if (!override_redirect) {
|
||||
long evmask = PropertyChangeMask;
|
||||
if (track_focus)
|
||||
evmask |= FocusChangeMask;
|
||||
XSelectInput(dpy, id, evmask);
|
||||
XSelectInput(dpy, id, determine_evmask(dpy, id, WIN_EVMODE_FRAME));
|
||||
// Notify compton when the shape of a window changes
|
||||
if (shape_exists) {
|
||||
XShapeSelectInput(dpy, id, ShapeNotifyMask);
|
||||
|
@ -1785,8 +1797,7 @@ add_win(Display *dpy, Window id, Window prev, Bool override_redirect) {
|
|||
get_frame_extents(dpy, cw,
|
||||
&new->left_width, &new->right_width,
|
||||
&new->top_width, &new->bottom_width);
|
||||
if (id != cw)
|
||||
XSelectInput(dpy, cw, PropertyChangeMask);
|
||||
XSelectInput(dpy, cw, determine_evmask(dpy, id, WIN_EVMODE_CLIENT));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2301,6 +2312,10 @@ inline static void
|
|||
ev_focus_in(XFocusChangeEvent *ev) {
|
||||
win *w = find_win(dpy, ev->window);
|
||||
|
||||
// To deal with events sent from windows just destroyed
|
||||
if (!w)
|
||||
return;
|
||||
|
||||
w->focused = True;
|
||||
calc_opacity(dpy, w, False);
|
||||
calc_dim(dpy, w);
|
||||
|
@ -2319,7 +2334,11 @@ ev_focus_out(XFocusChangeEvent *ev) {
|
|||
|
||||
win *w = find_win(dpy, ev->window);
|
||||
|
||||
// To deal with events sent from windows just destroyed
|
||||
if (!w)
|
||||
return;
|
||||
w->focused = False;
|
||||
|
||||
calc_opacity(dpy, w, False);
|
||||
calc_dim(dpy, w);
|
||||
}
|
||||
|
@ -2358,6 +2377,9 @@ ev_reparent_notify(XReparentEvent *ev) {
|
|||
add_win(dpy, ev->window, 0, ev->override_redirect);
|
||||
} else {
|
||||
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