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]

Reply via email to