move the focus_order lists into the kernel
authorDana Jansens <danakj@orodu.net>
Wed, 19 Mar 2003 07:08:15 +0000 (07:08 +0000)
committerDana Jansens <danakj@orodu.net>
Wed, 19 Mar 2003 07:08:15 +0000 (07:08 +0000)
openbox/client.c
openbox/dispatch.h
openbox/focus.c
openbox/focus.h
openbox/openbox.c
openbox/screen.c
plugins/focus.c

index 790dba5..dfc7034 100644 (file)
@@ -214,6 +214,7 @@ void client_unmanage_all()
 
 void client_unmanage(Client *client)
 {
+    guint i;
     int j;
     GSList *it;
 
@@ -242,6 +243,15 @@ void client_unmanage(Client *client)
     stacking_list = g_list_remove(stacking_list, client);
     g_hash_table_remove(client_map, (gpointer)client->window);
 
+    /* update the focus lists */
+    if (client->desktop == DESKTOP_ALL) {
+        for (i = 0; i < screen_num_desktops; ++i)
+            focus_order[i] = g_list_remove(focus_order[i], client);
+    } else {
+        i = client->desktop;
+        focus_order[i] = g_list_remove(focus_order[i], client);
+    }
+
     /* once the client is out of the list, update the struts to remove it's
        influence */
     screen_update_struts();
@@ -257,7 +267,7 @@ void client_unmanage(Client *client)
        client_calc_layer(it->data);
     }
 
-    /* unfocus the client (calls the focus callbacks) (we're out of the
+    /* unfocus the client (dispatchs the focus event) (we're out of the
      transient lists already, so being modal doesn't matter) */
     if (client->focused)
        client_unfocus(client);
@@ -1622,7 +1632,7 @@ void client_close(Client *self)
 
 void client_set_desktop(Client *self, guint target)
 {
-    guint old;
+    guint old, i;
 
     if (target == self->desktop) return;
   
@@ -1639,6 +1649,20 @@ void client_set_desktop(Client *self, guint target)
     client_showhide(self);
     screen_update_struts();
 
+    /* update the focus lists */
+    if (old == DESKTOP_ALL) {
+        for (i = 0; i < screen_num_desktops; ++i)
+            focus_order[i] = g_list_remove(focus_order[i], self);
+    } else {
+        focus_order[old] = g_list_remove(focus_order[old], self);
+    }
+    if (target == DESKTOP_ALL) {
+        for (i = 0; i < screen_num_desktops; ++i)
+            focus_order[i] = g_list_prepend(focus_order[i], self);
+    } else {
+        focus_order[target] = g_list_prepend(focus_order[target], self);
+    }
+
     dispatch_client(Event_Client_Desktop, self, target, old);
 }
 
index 5fa22e0..a283862 100644 (file)
@@ -20,9 +20,10 @@ typedef enum {
     Event_Client_New      = 1 << 8, /* new window, before mapping */
     Event_Client_Mapped   = 1 << 9, /* new window, after mapping */
     Event_Client_Destroy  = 1 << 10, /* unmanaged */
-    Event_Client_Focus    = 1 << 11, /* focused */
-    Event_Client_Unfocus  = 1 << 12, /* unfocused */
-    Event_Client_Urgent   = 1 << 13, /* entered/left urgent state */
+    Event_Client_Unmapped = 1 << 11, /* unmanaged, after unmapping */
+    Event_Client_Focus    = 1 << 12, /* focused */
+    Event_Client_Unfocus  = 1 << 13, /* unfocused */
+    Event_Client_Urgent   = 1 << 14, /* entered/left urgent state */
     Event_Client_Desktop  = 1 << 15, /* moved to a new desktop */
 
     Event_Ob_Desktop      = 1 << 16, /* changed desktops */
index cfc3485..d09494b 100644 (file)
@@ -5,8 +5,10 @@
 #include "dispatch.h"
 
 #include <X11/Xlib.h>
+#include <glib.h>
 
 Client *focus_client = NULL;
+GList **focus_order = NULL;
 
 Window focus_backup = None;
 
@@ -14,6 +16,8 @@ void focus_set_client(Client *client);
 
 void focus_startup()
 {
+    guint i;
+
     /* create the window which gets focus when no clients get it. Have to
        make it override-redirect so we don't try manage it, since it is
        mapped. */
@@ -25,14 +29,31 @@ void focus_startup()
                                 CopyFromParent, CWOverrideRedirect, &attrib);
     XMapRaised(ob_display, focus_backup);
 
+    focus_order = g_new(GList*, screen_num_desktops);
+    for (i = 0; i < screen_num_desktops; ++i)
+        focus_order[i] = NULL;
+
     /* start with nothing focused */
     focus_set_client(NULL);
 }
 
+void focus_shutdown()
+{
+    guint i;
+
+    for (i = 0; i < screen_num_desktops; ++i)
+        g_list_free(focus_order[i]);
+    g_free(focus_order);
+
+    /* reset focus to root */
+    XSetInputFocus(ob_display, PointerRoot, RevertToNone, CurrentTime);
+}
+
 void focus_set_client(Client *client)
 {
     Window active;
     Client *old;
+    guint desktop;
 
     /* uninstall the old colormap, and install the new one */
     screen_install_colormap(focus_client, FALSE);
@@ -47,6 +68,14 @@ void focus_set_client(Client *client)
     old = focus_client;
     focus_client = client;
 
+    /* move to the top of the list */
+    if (client != NULL) {
+        desktop = client->desktop;
+        if (desktop == DESKTOP_ALL) desktop = screen_desktop;
+        focus_order[desktop] = g_list_remove(focus_order[desktop], client);
+        focus_order[desktop] = g_list_prepend(focus_order[desktop], client);
+    }
+
     /* set the NET_ACTIVE_WINDOW hint */
     active = client ? client->window : None;
     PROP_SET32(ob_root, net_active_window, window, active);
index 9db5202..cb9a9a9 100644 (file)
@@ -2,6 +2,7 @@
 #define __focus_h
 
 #include <X11/Xlib.h>
+#include <glib.h>
 
 struct Client;
 
@@ -11,7 +12,11 @@ extern Window focus_backup;
 /*! The client which is currently focused */
 extern struct Client *focus_client;
 
+/*! The recent focus order on each desktop */
+extern GList **focus_order;
+
 void focus_startup();
+void focus_shutdown();
 
 /*! Specify which client is currently focused, this doesn't actually
   send focus anywhere, its called by the Focus event handlers */
index c9d8827..9f90a9e 100644 (file)
@@ -160,6 +160,7 @@ int main(int argc, char **argv)
         plugin_shutdown(); /* calls all the plugins' shutdown functions */
         grab_shutdown();
        client_shutdown();
+       focus_shutdown();
        screen_shutdown();
        event_shutdown();
        engine_shutdown();
@@ -168,8 +169,6 @@ int main(int argc, char **argv)
        timer_shutdown();
     }
 
-    /* reset focus to root before exiting */
-    XSetInputFocus(ob_display, PointerRoot, RevertToNone, CurrentTime);
     XCloseDisplay(ob_display);
 
     dispatch_shutdown();
index 8f60029..01acbfe 100644 (file)
@@ -195,7 +195,7 @@ void screen_resize()
 
 void screen_set_num_desktops(guint num)
 {
-    guint old;
+    guint i, old;
     gulong *viewport;
      
     g_assert(num > 0);
@@ -237,6 +237,16 @@ void screen_set_num_desktops(guint num)
     /* may be some unnamed desktops that we need to fill in with names */
     screen_update_desktop_names();
 
+    /* update the focus lists */
+    /* free our lists for the desktops which have disappeared */
+    for (i = num; i < old; ++i)
+        g_list_free(focus_order[i]);
+    /* realloc the array */
+    focus_order = g_renew(GList*, focus_order, num);
+    /* set the new lists to be empty */
+    for (i = old; i < num; ++i)
+        focus_order[i] = NULL;
+
     dispatch_ob(Event_Ob_NumDesktops, num, old);
 
     /* change our desktop if we're on one that no longer exists! */
index b713a84..d4ce4b9 100644 (file)
@@ -5,16 +5,27 @@
 #include "../kernel/stacking.h"
 #include "../kernel/openbox.h"
 
-static GSList **focus_order = NULL;
+static int skip_enter = 0;
 
 static void focus_fallback(guint desk, gboolean warp)
 {
-    GSList *it;
+    GList *it;
 
     for (it = focus_order[desk]; it != NULL; it = it->next)
         if (client_focus(it->data)) {
             if (warp) { /* XXX make this configurable */
+                XEvent e;
                 Client *c = it->data;
+
+                /* skip the next enter event from the desktop switch so focus
+                   doesn't skip briefly to what was under the pointer */
+                if (XCheckTypedEvent(ob_display, EnterNotify, &e)) {
+                    XPutBackEvent(ob_display, &e);
+                    ++skip_enter;
+                }
+
+                XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
+                             c->area.width / 2, c->area.height / 2);
                 XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
                              c->area.width / 2, c->area.height / 2);
             }
@@ -24,9 +35,6 @@ static void focus_fallback(guint desk, gboolean warp)
 
 static void events(ObEvent *e, void *foo)
 {
-    guint i;
-    guint new, old;
-
     switch (e->type) {
     case Event_Client_Mapped:
         /* focus new normal windows */
@@ -34,57 +42,31 @@ static void events(ObEvent *e, void *foo)
             client_focus(e->data.c.client);
         break;
 
-    case Event_Client_Destroy:
-        i = e->data.c.client->desktop;
-        focus_order[i] = g_slist_remove(focus_order[i], e->data.c.client);
-        break;
-
-    case Event_Ob_NumDesktops:
-        new = e->data.o.num[0];
-        old = e->data.o.num[1];
-        /* free our lists for the desktops which have disappeared */
-        for (i = new; i < old; ++i)
-            g_slist_free(focus_order[i]);
-        /* realloc the array */
-        focus_order = g_renew(GSList*, focus_order, new);
-        /* set the new lists to be empty */
-        for (i = old; i < new; ++i)
-            focus_order[i] = NULL;
-        break;
-
-    case Event_Client_Desktop:
-        old = e->data.c.num[1];
-        if (old != DESKTOP_ALL)
-            focus_order[old] = g_slist_remove(focus_order[old],
-                                              e->data.c.client);
-        else
-            for (i = 0; i < screen_num_desktops; ++i)
-                focus_order[i] = g_slist_remove(focus_order[i],
-                                                e->data.c.client);
-        break;
-
     case Event_Ob_Desktop:
+        g_message("Desktop Switch");
         /* focus the next available target */
         focus_fallback(e->data.o.num[0], TRUE);
         break;
 
     case Event_Client_Unfocus:
-        /* nothing is left with focus! */
+        /* dont do this shit with sloppy focus... */
+        /*
+        /\* nothing is left with focus! *\/
         if (focus_client == NULL) 
-            /* focus the next available target */
+            /\* focus the next available target *\/
             focus_fallback(screen_desktop, FALSE);
+        */
         break;
 
-    case Event_Client_Focus:
-        /* move to the top of the list */
-        focus_order[e->data.c.num[1]] =
-        g_slist_remove(focus_order[e->data.c.num[1]], e->data.c.client);
-        focus_order[e->data.c.num[1]] =
-        g_slist_prepend(focus_order[e->data.c.num[1]], e->data.c.client);
+    case Event_X_LeaveNotify:
+        g_message("Leave: %lx", e->data.x.client ? e->data.x.client->window : 0);
         break;
 
     case Event_X_EnterNotify:
-        if (e->data.x.client && client_normal(e->data.x.client))
+        g_message("Enter: %lx", e->data.x.client ? e->data.x.client->window : 0);
+        if (skip_enter)
+            --skip_enter;
+        else if (e->data.x.client && client_normal(e->data.x.client))
             client_focus(e->data.x.client);
         break;
 
@@ -95,27 +77,15 @@ static void events(ObEvent *e, void *foo)
 
 void plugin_startup()
 {
-    guint i;
-
-    dispatch_register(Event_Client_Mapped | Event_Client_Destroy |
-                      Event_Ob_Desktop | Event_Ob_NumDesktops |
-                      Event_Client_Focus | Event_Client_Unfocus |
+    dispatch_register(Event_Client_Mapped | 
+                      Event_Ob_Desktop | 
+                      Event_Client_Unfocus |
                       Event_X_EnterNotify |
-                      Event_Client_Desktop,
+                      Event_X_LeaveNotify,
                       (EventHandler)events, NULL);
-
-    focus_order = g_new(GSList*, screen_num_desktops);
-    for (i = 0; i < screen_num_desktops; ++i)
-        focus_order[i] = NULL;
 }
 
 void plugin_shutdown()
 {
-    guint i;
-
     dispatch_register(0, (EventHandler)events, NULL);
-
-    for (i = 0; i < screen_num_desktops; ++i)
-        g_slist_free(focus_order[i]);
-    g_free(focus_order);
 }