merge r6016-6018 from trunk
authorDana Jansens <danakj@orodu.net>
Fri, 4 May 2007 02:48:56 +0000 (02:48 +0000)
committerDana Jansens <danakj@orodu.net>
Fri, 4 May 2007 02:48:56 +0000 (02:48 +0000)
openbox/client.c
openbox/event.c

index c7859ca67838fa87dfd5c65789d18b24783f44c3..df0102c7a726403128b629108aebca99422d7b13 100644 (file)
@@ -381,8 +381,10 @@ void client_manage(Window window)
             focus_client->user_time : CurrentTime;
 
         /* This is focus stealing prevention */
-        ob_debug("Want to focus new window 0x%x with time %u (last time %u)\n",
-                 self->window, self->user_time, last_time);
+        ob_debug_type(OB_DEBUG_FOCUS,
+                      "Want to focus new window 0x%x with time %u "
+                      "(last time %u)\n",
+                      self->window, self->user_time, last_time);
 
         /* if it's on another desktop */
         if (!(self->desktop == screen_desktop || self->desktop == DESKTOP_ALL)
@@ -391,31 +393,38 @@ void client_manage(Window window)
             !event_time_after(self->user_time, screen_desktop_user_time))
         {
             activate = FALSE;
+            ob_debug_type(OB_DEBUG_FOCUS,
+                          "Not focusing the window because its on another "
+                          "desktop\n");
         }
-        /* If nothing is focused, or a parent was focused, then focus this
-           always
-        */
-        else if (!focus_client || client_search_focus_parent(self) != NULL)
-            activate = TRUE;
-        else
+        /* If something is focused, and it's not our parent... */
+        else if (focus_client && client_search_focus_parent(self) == NULL)
         {
             /* If time stamp is old, don't steal focus */
             if (self->user_time && last_time &&
                 !event_time_after(self->user_time, last_time))
             {
                 activate = FALSE;
+                ob_debug_type(OB_DEBUG_FOCUS,
+                              "Not focusing the window because the time is "
+                              "too old\n");
             }
             /* Don't steal focus from globally active clients.
                I stole this idea from KWin. It seems nice.
              */
-            if (!(focus_client->can_focus || focus_client->focus_notify))
+            if (!(focus_client->can_focus || focus_client->focus_notify)) {
                 activate = FALSE;
+                ob_debug_type(OB_DEBUG_FOCUS,
+                              "Not focusing the window because a globally "
+                              "active client has focus\n");
+            }
         }
 
         if (!activate) {
-            ob_debug("Focus stealing prevention activated for %s with time %u "
-                     "(last time %u)\n",
-                     self->title, self->user_time, last_time);
+            ob_debug_type(OB_DEBUG_FOCUS,
+                          "Focus stealing prevention activated for %s with "
+                          "time %u (last time %u)\n",
+                          self->title, self->user_time, last_time);
             /* if the client isn't focused, then hilite it so the user
                knows it is there */
             client_hilite(self, TRUE);
@@ -494,22 +503,8 @@ void client_unmanage(ObClient *self)
     /* update the focus lists */
     focus_order_remove(self);
     if (client_focused(self)) {
-        /* we have to fall back here because we might not get a focus out.
-           1. we need to xselectinput off the window before we unmap it because
-           otherwise we end up getting unmapnotifies we don't want and they
-           can mess up mapping it again quickly
-           2. this means that if we unmanage from a synthetic unmapnotify, we
-              are the ones unmapped it, and causing the focusout. so we won't
-              get the focusout event.
-           3. we can't handle focusin events on the root window because they
-              come from all screens, so the focus change gets lost
-
-           if this ever gets removed in the future MAKE SURE to replace it
-           with:
-           /- don't leave an invalid focus_client -/
-           focus_client = NULL;
-        */
-        focus_fallback(FALSE);
+        /* don't leave an invalid focus_client */
+        focus_client = NULL;
     }
 
     client_list = g_list_remove(client_list, self);
index d4ac2176e0e408ae580ae92c7b8bcac7ba0b5190..ff9ea5745b85c314390a1c4e6ddc0932cc5d6228 100644 (file)
@@ -96,6 +96,7 @@ Time event_curtime = CurrentTime;
 
 static guint ignore_enter_focus = 0;
 static gboolean menu_can_hide;
+static gboolean focus_left_screen = FALSE;
 
 #ifdef USE_SM
 static void ice_handler(gint fd, gpointer conn)
@@ -415,7 +416,23 @@ static void event_process(const XEvent *ec, gpointer data)
         /* crossing events for menu */
         event_handle_menu(e);
     } else if (e->type == FocusIn) {
-        if (client && client != focus_client) {
+        if (e->xfocus.detail == NotifyPointerRoot ||
+            e->xfocus.detail == NotifyDetailNone)
+        {
+            ob_debug_type(OB_DEBUG_FOCUS, "Focus went to pointer root/none\n");
+            /* Focus has been reverted to the root window or nothing.
+               FocusOut events come after UnmapNotify, so we don't need to
+               worry about focusing an invalid window
+             */
+            if (!focus_left_screen)
+                focus_fallback(TRUE);
+        } else if (e->xfocus.detail == NotifyInferior) {
+            ob_debug_type(OB_DEBUG_FOCUS,
+                          "Focus went to root or our frame window");
+            /* Focus has been given to the root window. */
+            focus_fallback(TRUE);
+        } else if (client && client != focus_client) {
+            focus_left_screen = FALSE;
             frame_adjust_focus(client->frame, TRUE);
             focus_set_client(client);
             client_calc_layer(client);
@@ -430,22 +447,28 @@ static void event_process(const XEvent *ec, gpointer data)
         if (!XCheckIfEvent(ob_display, &ce, look_for_focusin, NULL)) {
             /* There is no FocusIn, this means focus went to a window that
                is not being managed, or a window on another screen. */
-            ob_debug_type(OB_DEBUG_FOCUS, "Focus went to a black hole !\n");
+            Window win, root;
+            gint i;
+            guint u;
+            xerror_set_ignore(TRUE);
+            if (XGetInputFocus(ob_display, &win, &i) != 0 &&
+                XGetGeometry(ob_display, win, &root, &i,&i,&u,&u,&u,&u) != 0 &&
+                root != RootWindow(ob_display, ob_screen))
+            {
+                ob_debug_type(OB_DEBUG_FOCUS,
+                              "Focus went to another screen !\n");
+                focus_left_screen = TRUE;
+            }
+            else
+                ob_debug_type(OB_DEBUG_FOCUS,
+                              "Focus went to a black hole !\n");
+            xerror_set_ignore(FALSE);
             /* nothing is focused */
             focus_set_client(NULL);
         } else if (ce.xany.window == e->xany.window) {
             ob_debug_type(OB_DEBUG_FOCUS, "Focus didn't go anywhere\n");
             /* If focus didn't actually move anywhere, there is nothing to do*/
             nomove = TRUE;
-        } else if (ce.xfocus.detail == NotifyPointerRoot ||
-                   ce.xfocus.detail == NotifyDetailNone ||
-                   ce.xfocus.detail == NotifyInferior) {
-            ob_debug_type(OB_DEBUG_FOCUS, "Focus went to root\n");
-            /* Focus has been reverted to the root window or nothing
-               FocusOut events come after UnmapNotify, so we don't need to
-               worry about focusing an invalid window
-             */
-            focus_fallback(TRUE);
         } else {
             /* Focus did move, so process the FocusIn event */
             ObEventData ed = { .ignored = FALSE };