summaryrefslogtreecommitdiffstats
path: root/compton.c
diff options
context:
space:
mode:
authorRichard Grenville <[email protected]>2012-09-13 22:30:18 +0800
committerRichard Grenville <[email protected]>2012-09-13 22:30:18 +0800
commit27197e24dbcb3177642d55f56571205fead2b16e (patch)
tree740ed8e81b529994db715bf37d4429881c88bccd /compton.c
parent3a0ba85d3b5872221d21891be06bf3c8dfabd851 (diff)
downloadtdebase-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.
Diffstat (limited to 'compton.c')
-rw-r--r--compton.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/compton.c b/compton.c
index 50a74d0f8..c2d4a221a 100644
--- a/compton.c
+++ b/compton.c
@@ -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));
}
}