eat enter events after unmanaging a window
authorDana Jansens <danakj@orodu.net>
Sun, 22 Apr 2007 13:53:28 +0000 (13:53 +0000)
committerDana Jansens <danakj@orodu.net>
Sun, 22 Apr 2007 13:53:28 +0000 (13:53 +0000)
change how focus falls back for windows being unmanaged, don't fall back immediately, instead wait for the focus out event and use it (break stuff maybe! yay)

openbox/client.c
openbox/event.c

index e801ac1..e7af570 100644 (file)
@@ -77,7 +77,6 @@ static void client_apply_startup_state(ObClient *self, gint x, gint y);
 static void client_restore_session_state(ObClient *self);
 static void client_restore_session_stacking(ObClient *self);
 static ObAppSettings *client_get_settings_state(ObClient *self);
-static void client_unfocus(ObClient *self);
 
 void client_startup(gboolean reconfig)
 {
@@ -507,8 +506,8 @@ void client_unmanage(ObClient *self)
 
     g_assert(self != NULL);
 
-    /* update the focus lists */
-    focus_order_remove(self);
+    frame_hide(self->frame);
+    XSync(ob_display, FALSE);
 
     if (focus_client == self) {
         XEvent e;
@@ -516,20 +515,8 @@ void client_unmanage(ObClient *self)
         /* focus the last focused window on the desktop, and ignore enter
            events from the unmap so it doesnt mess with the focus */
         while (XCheckTypedEvent(ob_display, EnterNotify, &e));
-        /* remove these flags so we don't end up getting focused in the
-           fallback! */
-        self->can_focus = FALSE;
-        self->focus_notify = FALSE;
-        self->modal = FALSE;
-        client_unfocus(self);
     }
 
-    /* potentially fix focusLast */
-    if (config_focus_last)
-        grab_pointer(TRUE, OB_CURSOR_NONE);
-
-    frame_hide(self->frame);
-    XFlush(ob_display);
 
     keyboard_grab_for_client(self, FALSE);
     mouse_grab_for_client(self, FALSE);
@@ -540,6 +527,9 @@ void client_unmanage(ObClient *self)
     /* we dont want events no more */
     XSelectInput(ob_display, self->window, NoEventMask);
 
+    /* update the focus lists */
+    focus_order_remove(self);
+
     client_list = g_list_remove(client_list, self);
     stacking_remove(self);
     g_hash_table_remove(window_map, &self->window);
@@ -639,9 +629,6 @@ void client_unmanage(ObClient *self)
      
     /* update the list hints */
     client_set_list();
-
-    if (config_focus_last)
-        grab_pointer(FALSE, OB_CURSOR_NONE);
 }
 
 static ObAppSettings *client_get_settings_state(ObClient *self)
@@ -3054,19 +3041,6 @@ gboolean client_focus(ObClient *self)
     return TRUE;
 }
 
-/* Used when the current client is closed or otherwise hidden, focus_last will
-   then prevent focus from going to the mouse pointer
-*/
-static void client_unfocus(ObClient *self)
-{
-    if (focus_client == self) {
-#ifdef DEBUG_FOCUS
-        ob_debug("client_unfocus for %lx\n", self->window);
-#endif
-        focus_fallback(FALSE);
-    }
-}
-
 void client_activate(ObClient *self, gboolean here, gboolean user)
 {
     guint32 last_time = focus_client ? focus_client->user_time : CurrentTime;
index 9a1e13d..4d74284 100644 (file)
@@ -398,12 +398,11 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
         return keyboard_interactively_grabbed();
     case FocusIn:
     case FocusOut:
-        /* I don't think this should ever happen with our event masks, but
-           if it does, we don't want it. */
-        if (client == NULL)
-            return TRUE;
-        if (!wanted_focusevent(e))
+        if (!wanted_focusevent(e)) {
+            ob_debug_type(OB_DEBUG_FOCUS, "focus event ignored\n");
             return TRUE;
+        }
+        ob_debug_type(OB_DEBUG_FOCUS, "focus event used;\n");
         break;
     }
     return FALSE;
@@ -485,6 +484,58 @@ static void event_process(const XEvent *ec, gpointer data)
     {
         /* crossing events for menu */
         event_handle_menu(e);
+    } else if (e->type == FocusIn) {
+        if (e->xfocus.detail == NotifyPointerRoot ||
+                   e->xfocus.detail == NotifyDetailNone) {
+            ob_debug_type(OB_DEBUG_FOCUS, "Focus went to root\n");
+            /* Focus has been reverted to the root window or nothing, so fall
+               back to something other than the window which just had it. */
+            focus_fallback(FALSE);
+        } else if (e->xfocus.detail == NotifyInferior) {
+            ob_debug_type(OB_DEBUG_FOCUS, "Focus went to parent\n");
+            /* Focus has been reverted to parent, which is our frame window,
+               or the root window, so fall back to something other than the
+               window which had it. */
+            focus_fallback(FALSE);
+        } else if (client && client != focus_client) {
+            focus_set_client(client);
+            frame_adjust_focus(client->frame, TRUE);
+            client_calc_layer(client);
+        }
+    } else if (e->type == FocusOut) {
+        gboolean nomove = FALSE;
+        XEvent ce;
+
+        ob_debug_type(OB_DEBUG_FOCUS, "FocusOut Event\n");
+
+        /* Look for the followup FocusIn */
+        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");
+        } else if (ce.xany.window == e->xany.window) {
+            /* If focus didn't actually move anywhere, there is nothing to do*/
+            nomove = TRUE;
+        } else {
+            /* Focus did move, so process the FocusIn event */
+            ObEventData ed = { .ignored = FALSE };
+            event_process(&ce, &ed);
+            if (ed.ignored) {
+                /* The FocusIn was ignored, this means it was on a window
+                   that isn't a client. */
+                ob_debug_type(OB_DEBUG_FOCUS,
+                              "Focus went to an unmanaged window 0x%x !\n",
+                              ce.xfocus.window);
+                focus_fallback(TRUE);
+            }
+        }
+
+        if (client && !nomove) {
+            /* This client is no longer focused, so show that */
+            focus_hilite = NULL;
+            frame_adjust_focus(client->frame, FALSE);
+            client_calc_layer(client);
+        }
     } else if (group)
         event_handle_group(group, e);
     else if (client)
@@ -690,53 +741,6 @@ static void event_handle_client(ObClient *client, XEvent *e)
             }
         }
         break;
-    case FocusIn:
-        if (client != focus_client) {
-            focus_set_client(client);
-            frame_adjust_focus(client->frame, TRUE);
-            client_calc_layer(client);
-        }
-        break;
-    case FocusOut:
-        /* Look for the followup FocusIn */
-        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");
-        } else if (ce.xany.window == e->xany.window) {
-            /* If focus didn't actually move anywhere, there is nothing to do*/
-            break;
-        } else if (ce.xfocus.detail == NotifyPointerRoot ||
-                 ce.xfocus.detail == NotifyDetailNone) {
-            ob_debug_type(OB_DEBUG_FOCUS, "Focus went to root\n");
-            /* Focus has been reverted to the root window or nothing, so fall
-               back to something other than the window which just had it. */
-            focus_fallback(FALSE);
-        } else if (ce.xfocus.detail == NotifyInferior) {
-            ob_debug_type(OB_DEBUG_FOCUS, "Focus went to parent\n");
-            /* Focus has been reverted to parent, which is our frame window,
-               or the root window, so fall back to something other than the
-               window which had it. */
-            focus_fallback(FALSE);
-        } else {
-            /* Focus did move, so process the FocusIn event */
-            ObEventData ed = { .ignored = FALSE };
-            event_process(&ce, &ed);
-            if (ed.ignored) {
-                /* The FocusIn was ignored, this means it was on a window
-                   that isn't a client. */
-                ob_debug_type(OB_DEBUG_FOCUS,
-                              "Focus went to an unmanaged window 0x%x !\n",
-                              ce.xfocus.window);
-                focus_fallback(TRUE);
-            }
-        }
-
-        /* This client is no longer focused, so show that */
-        focus_hilite = NULL;
-        frame_adjust_focus(client->frame, FALSE);
-        client_calc_layer(client);
-        break;
     case LeaveNotify:
         con = frame_context(client, e->xcrossing.window);
         switch (con) {