diff options
author | Richard Grenville <[email protected]> | 2012-09-13 22:30:18 +0800 |
---|---|---|
committer | Richard Grenville <[email protected]> | 2012-09-13 22:30:18 +0800 |
commit | 27197e24dbcb3177642d55f56571205fead2b16e (patch) | |
tree | 740ed8e81b529994db715bf37d4429881c88bccd | |
parent | 3a0ba85d3b5872221d21891be06bf3c8dfabd851 (diff) | |
download | tdebase-27197e24dbcb3177642d55f56571205fead2b16e.tar.gz tdebase-27197e24dbcb3177642d55f56571205fead2b16e.zip |
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.
-rw-r--r-- | compton.c | 34 |
1 files changed, 28 insertions, 6 deletions
@@ -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)); } } |