track window groups
authorDana Jansens <danakj@orodu.net>
Mon, 7 Apr 2003 05:47:20 +0000 (05:47 +0000)
committerDana Jansens <danakj@orodu.net>
Mon, 7 Apr 2003 05:47:20 +0000 (05:47 +0000)
iconify all its transients when a window is iconified

openbox/client.c
openbox/client.h
openbox/group.c [new file with mode: 0644]
openbox/group.h [new file with mode: 0644]
openbox/openbox.c

index 1b1feda..2c6082b 100644 (file)
@@ -9,6 +9,7 @@
 #include "focus.h"
 #include "stacking.h"
 #include "dispatch.h"
+#include "group.h"
 
 #include <glib.h>
 #include <X11/Xutil.h>
@@ -319,6 +320,10 @@ void client_unmanage(Client *client)
            XMapWindow(ob_display, client->window);
     }
 
+    /* remoev from its group */
+    if (client->group)
+        group_remove(client->group, client);
+
     /* free all data allocated in the client struct */
     g_slist_free(client->transients);
     for (j = 0; j < client->nicons; ++j)
@@ -420,7 +425,7 @@ static void client_get_all(Client *self)
     self->urgent = FALSE;
     self->positioned = FALSE;
     self->disabled_decorations = 0;
-    self->group = None;
+    self->group = NULL;
     self->nicons = 0;
 
     client_get_area(self);
@@ -940,10 +945,12 @@ void client_update_wmhints(Client *self)
            ur = TRUE;
 
        if (hints->flags & WindowGroupHint) {
-           if (hints->window_group != self->group) {
-               /* XXX: remove from the old group if there was one */
-               self->group = hints->window_group;
-               /* XXX: do stuff with the group */
+           if (hints->window_group !=
+                (self->group ? self->group->leader : None)) {
+               /* remove from the old group if there was one */
+                if (self->group != NULL)
+                    group_remove(self->group, self);
+               self->group = group_add(hints->window_group, self);
            }
        } else /* no group! */
            self->group = None;
@@ -1554,6 +1561,14 @@ void client_iconify(Client *self, gboolean iconic, gboolean curdesk)
 
     dispatch_client(iconic ? Event_Client_Unmapped : Event_Client_Mapped,
                     self, 0, 0);
+
+    /* iconify all transients */
+    if (self->transients) {
+        GSList *it;
+
+        for (it = self->transients; it != NULL; it = it->next)
+            if (it->data != self) client_iconify(it->data, iconic, curdesk);
+    }
 }
 
 void client_maximize(Client *self, gboolean max, int dir, gboolean savearea)
index 89bdb51..1e801dc 100644 (file)
@@ -7,7 +7,7 @@
 #include <X11/Xlib.h>
 
 struct Frame;
-
+struct Group;
 
 /*! Holds an icon in ARGB format */
 typedef struct Icon {
@@ -114,7 +114,7 @@ typedef struct Client {
     int ignore_unmaps;
 
     /*! The id of the group the window belongs to */
-    Window  group;
+    struct Group *group;
     /*! Whether or not the client is a transient window. This is guaranteed to 
       be TRUE if transient_for != NULL, but not guaranteed to be FALSE if
       transient_for == NULL. */
diff --git a/openbox/group.c b/openbox/group.c
new file mode 100644 (file)
index 0000000..69d2ccb
--- /dev/null
@@ -0,0 +1,46 @@
+#include "group.h"
+#include "client.h"
+
+GHashTable *group_map = NULL;
+
+static guint map_hash(Window *w) { return *w; }
+static gboolean map_key_comp(Window *w1, Window *w2) { return *w1 == *w2; }
+
+void group_startup()
+{
+    group_map = g_hash_table_new((GHashFunc)map_hash,
+                                 (GEqualFunc)map_key_comp);
+}
+
+void group_shutdown()
+{
+    g_hash_table_destroy(group_map);
+}
+
+Group *group_add(Window leader, Client *client)
+{
+    Group *self;
+
+    self = g_hash_table_lookup(group_map, &leader);
+    if (self == NULL) {
+        self = g_new(Group, 1);
+        self->leader = leader;
+        self->members = NULL;
+        g_hash_table_insert(group_map, &self->leader, self);
+        g_message("NEW GROUP FOR %lx", leader);
+    } else
+        g_message("REUSING GROUP FOR %lx", leader);
+
+    self->members = g_slist_append(self->members, client);
+
+    return self;
+}
+
+void group_remove(Group *self, Client *client)
+{
+    self->members = g_slist_remove(self->members, client);
+    if (self->members == NULL) {
+        g_hash_table_remove(group_map, &self->leader);
+        g_free(self);
+    }
+}
diff --git a/openbox/group.h b/openbox/group.h
new file mode 100644 (file)
index 0000000..dfc6e88
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __group_h
+#define __group_h
+
+#include <X11/Xlib.h>
+#include <glib.h>
+
+struct Client;
+
+typedef struct Group {
+    Window leader;
+
+    /* list of clients */
+    GSList *members;
+} Group;
+
+extern GHashTable *group_map;
+
+void group_startup();
+void group_shutdown();
+
+Group *group_add(Window leader, struct Client *client);
+
+void group_remove(Group *self, struct Client *client);
+
+#endif
index 3d4db6f..74f8164 100644 (file)
@@ -12,6 +12,7 @@
 #include "engine.h"
 #include "plugin.h"
 #include "timer.h"
+#include "group.h"
 #include "gettext.h"
 #include "../render/render.h"
 #include "../render/font.h"
@@ -172,6 +173,7 @@ int main(int argc, char **argv)
        engine_load();
 
        screen_startup();
+        group_startup();
        client_startup();
 
         /* call startup for all the plugins */
@@ -189,6 +191,7 @@ int main(int argc, char **argv)
 
         plugin_shutdown(); /* calls all the plugins' shutdown functions */
        client_shutdown();
+        group_shutdown();
        screen_shutdown();
        focus_shutdown();
        engine_shutdown();