On Friday 16 July 2004 09:25, Robert Marshall wrote:
> Since updating yesterday, I've seen quite a few crashes, typically
> what's happening is
>
> close window
> attempt to switch workspace using bbkeys - nothing happens
> bring up menu with mouse - crash! (or use mouse to attempt to change
> workspaces)
fun fun, blackbox is losing track of the focus :)
> I get a number of rather different tracebacks here's the latest
>
> Loaded symbols for
> /usr/X11R6/lib/X11/locale/lib/common/xomGeneric.so.2 #0
> Toolbar::redrawWindowLabel() (this=0x8106510) at char_traits.h:127
> 127 { __c1 = __c2; }
> (gdb) where
> #0 Toolbar::redrawWindowLabel() (this=0x8106510)
blackbox->getFocusedWindow() is returning a dangling pointer...
> #0 Blackbox::setFocusedWindow(BlackboxWindow*) (this=0xbffff700,
> win=0x1800030)
focused_window is a dangling pointer, and trying to call
setFocused(false) on it results in this crash.
> maybe it's another symptom of the memory corruption I'm seeing
> elsewhere?
I've been trying to clean this up some. Attached is a patch that I've
been working on the past week. I have been running it for a few days
now, and it seems ok, but there might be some kinks to iron out. Give
it a shot, if you dare :)
> Robert
--
Bradley T. Hughes - bhughes at trolltech.com
Trolltech AS - Waldemar Thranes gt. 98 N-0175 Oslo, Norway
Index: src/Window.cc
===================================================================
RCS file: /cvsroot/blackboxwm/blackbox/src/Window.cc,v
retrieving revision 1.340
diff -b -u -r1.340 Window.cc
--- src/Window.cc 12 Jul 2004 11:48:35 -0000 1.340
+++ src/Window.cc 16 Jul 2004 08:21:33 -0000
@@ -248,8 +248,7 @@
// set the eventmask early in the game so that we make sure we get
// all the events we are interested in
XSetWindowAttributes attrib_set;
- attrib_set.event_mask = PropertyChangeMask | FocusChangeMask |
- StructureNotifyMask;
+ attrib_set.event_mask = PropertyChangeMask | StructureNotifyMask;
attrib_set.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask;
XChangeWindowAttributes(blackbox->XDisplay(), client.window,
@@ -543,8 +542,7 @@
XSelectInput(blackbox->XDisplay(), frame.plate,
FocusChangeMask | SubstructureRedirectMask);
- unsigned long event_mask = PropertyChangeMask | FocusChangeMask |
- StructureNotifyMask;
+ unsigned long event_mask = PropertyChangeMask | StructureNotifyMask;
XSelectInput(blackbox->XDisplay(), client.window,
event_mask & ~StructureNotifyMask);
XReparentWindow(blackbox->XDisplay(), client.window, frame.plate, 0, 0);
@@ -1568,23 +1566,14 @@
// transfer focus to any modal transients
BlackboxWindowList::iterator it, end = client.transientList.end();
for (it = client.transientList.begin(); it != end; ++it) {
- if ((*it)->isModal())
- return (*it)->setInputFocus();
+ BlackboxWindow * const tmp = *it;
+ if (tmp->isVisible() && tmp->isModal())
+ return tmp->setInputFocus();
}
}
- if (client.wmhints.accept_focus) {
XSetInputFocus(blackbox->XDisplay(), client.window,
RevertToPointerRoot, blackbox->XTime());
- } else {
- /*
- * we could set the focus to none, since the window doesn't accept
- * focus, but we shouldn't set focus to nothing since this would
- * surely make someone angry. instead, set the focus to the plate
- */
- XSetInputFocus(blackbox->XDisplay(), frame.plate,
- RevertToPointerRoot, blackbox->XTime());
- }
if (client.wmprotocols.wm_take_focus) {
XEvent ce;
@@ -1601,8 +1590,6 @@
XSendEvent(blackbox->XDisplay(), client.window, False, NoEventMask, &ce);
}
- blackbox->setFocusedWindow(this);
-
return true;
}
@@ -1656,8 +1643,7 @@
* could be destroyed in that split second, leaving us with a ghost
* window... so, we need to do this while the X server is grabbed
*/
- unsigned long event_mask = PropertyChangeMask | FocusChangeMask |
- StructureNotifyMask;
+ unsigned long event_mask = PropertyChangeMask | StructureNotifyMask;
blackbox->XGrabServer();
XSelectInput(blackbox->XDisplay(), client.window,
event_mask & ~StructureNotifyMask);
@@ -1912,14 +1898,15 @@
void BlackboxWindow::setFocused(bool focused) {
- if (focused && !isVisible()) return;
+ if (focused == client.state.focused)
+ return;
- client.state.focused = focused;
+ client.state.focused = isVisible() ? focused : false;
+ if (isVisible()) {
redrawWindowFrame();
- if (client.state.focused) {
- blackbox->setFocusedWindow(this);
+ if (client.state.focused)
XInstallColormap(blackbox->XDisplay(), client.colormap);
}
}
@@ -3196,7 +3183,7 @@
void BlackboxWindow::enterNotifyEvent(const XCrossingEvent * const event) {
- if (event->window != frame.window)
+ if (event->window != frame.window || event->mode != NotifyNormal)
return;
if (!screen->resource().isSloppyFocus() || !isVisible())
Index: src/blackbox.cc
===================================================================
RCS file: /cvsroot/blackboxwm/blackbox/src/blackbox.cc,v
retrieving revision 1.153
diff -b -u -r1.153 blackbox.cc
--- src/blackbox.cc 12 Jul 2004 11:53:22 -0000 1.153
+++ src/blackbox.cc 16 Jul 2004 08:21:33 -0000
@@ -39,6 +39,19 @@
#include <signal.h>
#include <unistd.h>
+// #define FOCUS_DEBUG
+
+
+static Bool scanForFocusIn(Display *, XEvent *e, XPointer) {
+ if (e->type == FocusIn
+ && (e->xfocus.mode == NotifyNormal
+ || e->xfocus.mode == NotifyWhileGrabbed)
+ && e->xfocus.detail == NotifyNonlinearVirtual) {
+ return true;
+ }
+ return false;
+}
+
Blackbox::Blackbox(char **m_argv, const char *dpy_name,
const std::string& rc, bool multi_head)
@@ -209,21 +222,55 @@
break;
}
+#ifdef FOCUS_DEBUG
+
+ static const char *Mode[] = {
+ "Normal",
+ "Grab",
+ "Ungrab",
+ "WhileGrabbed"
+ };
+
+ static const char *Detail[] = {
+ "Ancestor",
+ "Virtual",
+ "Inferior",
+ "Nonlinear",
+ "NonlinearVirtual",
+ "Pointer",
+ "PointerRoot",
+ "DetailNone"
+ };
+
+#endif // FOCUS_DEBUG
+
case FocusIn: {
- if (e->xfocus.detail != NotifyNonlinear) {
+#ifdef FOCUS_DEBUG
+ printf("FocusIn : window %8lx mode %s detail %s\n",
+ e->xfocus.window, Mode[e->xfocus.mode], Detail[e->xfocus.detail]);
+#endif
+
+ if ((e->xfocus.mode != NotifyNormal
+ && e->xfocus.mode != NotifyWhileGrabbed)
+ || e->xfocus.detail != NotifyNonlinearVirtual) {
/*
don't process FocusIns when:
- 1. the new focus window isn't an ancestor or inferior of the
- old focus window (NotifyNonlinear)
+ 1. they are the result of a grab
+ 2. the new focus window isn't an ancestor or inferior of the
+ old focus window (NotifyNonlinearVirtual)
*/
break;
}
BlackboxWindow *win = findWindow(e->xfocus.window);
- if (!win) break;
+ if (!win || win->isFocused())
+ break;
- if (!win->isFocused())
+#ifdef FOCUS_DEBUG
+ printf(" win %p got focus\n", win);
+#endif
win->setFocused(true);
+ setFocusedWindow(win);
/*
set the event window to None. when the FocusOut event handler calls
@@ -231,67 +278,50 @@
has moved to a known window.
*/
e->xfocus.window = None;
+
break;
}
case FocusOut: {
- if (e->xfocus.detail != NotifyNonlinear) {
+#ifdef FOCUS_DEBUG
+ printf("FocusOut: window %8lx mode %s detail %s\n",
+ e->xfocus.window, Mode[e->xfocus.mode], Detail[e->xfocus.detail]);
+#endif
+
+ if ((e->xfocus.mode != NotifyNormal
+ && e->xfocus.mode != NotifyWhileGrabbed)
+ || e->xfocus.detail != NotifyNonlinearVirtual) {
/*
don't process FocusOuts when:
- 1. the new focus window isn't an ancestor or inferior of the
- old focus window (NotifyNonlinear)
+ 1. they are the result of a grab
+ 2. the new focus window isn't an ancestor or inferior of the
+ old focus window (NotifyNonlinearVirtual)
*/
break;
}
BlackboxWindow *win = findWindow(e->xfocus.window);
- if (!win || !win->isFocused()) break;
+ if (!win || !win->isFocused())
+ break;
- /*
- before we mark "win" as unfocused, we need to verify that focus
- is going to a known location, is in a known location, or set
- focus to a known location.
- */
+#ifdef FOCUS_DEBUG
+ printf(" win %p lost focus\n", win);
+#endif
+ win->setFocused(false);
XEvent event;
- // don't check the current focus if FocusOut was generated by a grab
- bool check_focus = (e->xfocus.mode != NotifyGrab);
-
- /*
- First, check if there is a pending FocusIn event waiting. if
- there is, process it and determine if focus has moved to another
- window (the FocusIn event handler sets the window in the event
- structure to None to indicate this).
- */
- if (XCheckTypedEvent(XDisplay(), FocusIn, &event)) {
-
+ bool clear_focus = true;
+ if (XCheckIfEvent(XDisplay(), &event, scanForFocusIn, NULL)) {
process_event(&event);
- if (event.xfocus.window == None) {
- // focus has moved
- check_focus = False;
- }
- }
- if (!check_focus) break;
+ if (event.xfocus.window == None)
+ clear_focus = false;
+ }
- /*
- Second, we query the X server for the current input focus. to
- make sure that we keep a consistent state.
- */
- BlackboxWindow *focus;
- Window w;
- int revert;
- XGetInputFocus(XDisplay(), &w, &revert);
- focus = findWindow(w);
- if (focus) {
- /*
- focus got from "win" to "focus" under some very strange
- circumstances, and we need to make sure that the focus
- indication is correct.
- */
- setFocusedWindow(focus);
- } else {
- // we have no idea where focus went... so we set it to PointerRoot
+ if (clear_focus) {
+#ifdef FOCUS_DEBUG
+ printf(" no window has focus\n");
+#endif
setFocusedWindow(0);
}
@@ -581,7 +611,6 @@
BScreen *old_screen = 0;
if (focused_window) {
- focused_window->setFocused(false);
old_screen = focused_window->getScreen();
if (focused_window->isFullScreen() &&
--
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
List archives: http://asgardsrealm.net/lurker/splash/index.html
Trouble? Contact [EMAIL PROTECTED]