diff --git a/server/CXWindowsPrimaryScreen.cpp b/server/CXWindowsPrimaryScreen.cpp index e5567393..c08dcd74 100644 --- a/server/CXWindowsPrimaryScreen.cpp +++ b/server/CXWindowsPrimaryScreen.cpp @@ -597,7 +597,9 @@ CXWindowsPrimaryScreen::onLostClipboard(ClipboardID id) void CXWindowsPrimaryScreen::selectEvents(Display* display, Window w) const { - // ignore errors while we adjust event masks + // ignore errors while we adjust event masks. windows could be + // destroyed at any time after the XQueryTree() in doSelectEvents() + // so we must ignore BadWindow errors. CXWindowsUtil::CErrorLock lock; // adjust event masks @@ -611,13 +613,28 @@ CXWindowsPrimaryScreen::doSelectEvents(Display* display, Window w) const // that we select PointerMotionMask on every window. we also select // SubstructureNotifyMask in order to get CreateNotify events so we // select events on new windows too. + // + // note that this can break certain clients due a design flaw of X. + // X will deliver a PointerMotion event to the deepest window in the + // hierarchy that contains the pointer and has PointerMotionMask + // selected by *any* client. if another client doesn't select + // motion events in a subwindow so the parent window will get them + // then by selecting for motion events on the subwindow we break + // that client because the parent will no longer get the events. + + // FIXME -- should provide some workaround for event selection + // design flaw. perhaps only select for motion events on windows + // that already do or are top-level windows or don't propagate + // pointer events. or maybe an option to simply poll the mouse. // we don't want to adjust our grab window if (w == m_window) { return; } - // select events of interest + // select events of interest. do this before querying the tree so + // we'll get notifications of children created after the XQueryTree() + // so we won't miss them. XSelectInput(display, w, PointerMotionMask | SubstructureNotifyMask); // recurse on child windows