]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
make helper windows share desktops with all their application top level windows
[chaz/openbox] / openbox / client.c
index 9c06e49e34d38e0bc50ee83b011eea47f25adab1..87156eb6d370c4b552e1860d230c33aa2208e149 100644 (file)
 
 typedef struct
 {
-    ObClientDestructor func;
+    ObClientCallback func;
     gpointer data;
-} Destructor;
+} ClientCallback;
 
-GList            *client_list        = NULL;
+GList            *client_list          = NULL;
 
-static GSList *client_destructors    = NULL;
+static GSList *client_destructors      = NULL;
+static GSList *client_desktop_notifies = NULL;
 
 static void client_get_all(ObClient *self);
 static void client_toggle_border(ObClient *self, gboolean show);
@@ -105,20 +106,20 @@ void client_shutdown(gboolean reconfig)
 {
 }
 
-void client_add_destructor(ObClientDestructor func, gpointer data)
+void client_add_destructor(ObClientCallback func, gpointer data)
 {
-    Destructor *d = g_new(Destructor, 1);
+    ClientCallback *d = g_new(ClientCallback, 1);
     d->func = func;
     d->data = data;
     client_destructors = g_slist_prepend(client_destructors, d);
 }
 
-void client_remove_destructor(ObClientDestructor func)
+void client_remove_destructor(ObClientCallback func)
 {
     GSList *it;
 
     for (it = client_destructors; it; it = g_slist_next(it)) {
-        Destructor *d = it->data;
+        ClientCallback *d = it->data;
         if (d->func == func) {
             g_free(d);
             client_destructors = g_slist_delete_link(client_destructors, it);
@@ -127,6 +128,29 @@ void client_remove_destructor(ObClientDestructor func)
     }
 }
 
+void client_add_desktop_notify(ObClientCallback func, gpointer data)
+{
+    ClientCallback *d = g_new(ClientCallback, 1);
+    d->func = func;
+    d->data = data;
+    client_desktop_notifies = g_slist_prepend(client_desktop_notifies, d);
+}
+
+void client_remove_desktop_notify(ObClientCallback func)
+{
+    GSList *it;
+
+    for (it = client_desktop_notifies; it; it = g_slist_next(it)) {
+        ClientCallback *d = it->data;
+        if (d->func == func) {
+            g_free(d);
+            client_desktop_notifies =
+                g_slist_delete_link(client_desktop_notifies, it);
+            break;
+        }
+    }
+}
+
 void client_set_list()
 {
     Window *windows, *win_it;
@@ -533,7 +557,7 @@ void client_unmanage(ObClient *self)
         screen_update_areas();
 
     for (it = client_destructors; it; it = g_slist_next(it)) {
-        Destructor *d = it->data;
+        ClientCallback *d = it->data;
         d->func(self, d->data);
     }
 
@@ -1254,11 +1278,13 @@ static void client_update_transient_tree(ObClient *self,
     }
             
 
-    /* If the group changed then we need to remove any old group transient
-       windows from our children. But if we're transient for the group, then
+    /* If the group changed, or if we are just becoming transient for the
+       group, then we need to remove any old group transient windows
+       from our children. But if we were already transient for the group, then
        other group transients are not our children. */
-    if (oldgroup != newgroup && oldgroup != NULL &&
-        oldparent != OB_TRAN_GROUP)
+    if ((oldgroup != newgroup ||
+         (newparent == OB_TRAN_GROUP && oldparent != newparent)) &&
+        oldgroup != NULL && oldparent != OB_TRAN_GROUP)
     {
         for (it = self->transients; it; it = next) {
             next = g_slist_next(it);
@@ -2143,9 +2169,11 @@ static void client_change_wm_state(ObClient *self)
 
     old = self->wmstate;
 
-    if (self->shaded || self->iconic)
+    if (self->shaded || self->iconic ||
+        (self->desktop != DESKTOP_ALL && self->desktop != screen_desktop))
+    {
         self->wmstate = IconicState;
-    else
+    else
         self->wmstate = NormalState;
 
     if (old != self->wmstate) {
@@ -2784,7 +2812,7 @@ static void client_iconify_recursive(ObClient *self,
 
             if (curdesk && self->desktop != screen_desktop &&
                 self->desktop != DESKTOP_ALL)
-                client_set_desktop(self, screen_desktop, FALSE);
+                client_set_desktop(self, screen_desktop, FALSE, FALSE);
 
             /* this puts it after the current focused window */
             focus_order_remove(self);
@@ -2964,7 +2992,9 @@ void client_hilite(ObClient *self, gboolean hilite)
 }
 
 void client_set_desktop_recursive(ObClient *self,
-                                  guint target, gboolean donthide)
+                                  guint target,
+                                  gboolean donthide,
+                                  gboolean focus_nonintrusive)
 {
     guint old;
     GSList *it;
@@ -2976,7 +3006,8 @@ void client_set_desktop_recursive(ObClient *self,
         g_assert(target < screen_num_desktops || target == DESKTOP_ALL);
 
         /* remove from the old desktop(s) */
-        focus_order_remove(self);
+        if (!focus_nonintrusive)
+            focus_order_remove(self);
 
         old = self->desktop;
         self->desktop = target;
@@ -2993,23 +3024,34 @@ void client_set_desktop_recursive(ObClient *self,
             screen_update_areas();
 
         /* add to the new desktop(s) */
-        if (config_focus_new)
-            focus_order_to_top(self);
-        else
-            focus_order_to_bottom(self);
+        if (!focus_nonintrusive) {
+            if (config_focus_new)
+                focus_order_to_top(self);
+            else
+                focus_order_to_bottom(self);
+        }
+
+        /* call the notifies */
+        GSList *it;
+        for (it = client_desktop_notifies; it; it = g_slist_next(it)) {
+            ClientCallback *d = it->data;
+            d->func(self, d->data);
+        }
     }
 
     /* move all transients */
     for (it = self->transients; it; it = g_slist_next(it))
         if (it->data != self)
             if (client_is_direct_child(self, it->data))
-                client_set_desktop_recursive(it->data, target, donthide);
+                client_set_desktop_recursive(it->data, target,
+                                             donthide, focus_nonintrusive);
 }
 
-void client_set_desktop(ObClient *self, guint target, gboolean donthide)
+void client_set_desktop(ObClient *self, guint target,
+                        gboolean donthide, gboolean focus_nonintrusive)
 {
     self = client_search_top_normal_parent(self);
-    client_set_desktop_recursive(self, target, donthide);
+    client_set_desktop_recursive(self, target, donthide, focus_nonintrusive);
 }
 
 gboolean client_is_direct_child(ObClient *parent, ObClient *child)
@@ -3343,7 +3385,7 @@ static void client_present(ObClient *self, gboolean here, gboolean raise)
         self->desktop != screen_desktop)
     {
         if (here)
-            client_set_desktop(self, screen_desktop, FALSE);
+            client_set_desktop(self, screen_desktop, FALSE, FALSE);
         else
             screen_set_desktop(self->desktop, FALSE);
     } else if (!self->frame->visible)
@@ -3391,6 +3433,26 @@ void client_activate(ObClient *self, gboolean here, gboolean user)
     }
 }
 
+static void client_bring_non_application_windows_recursive(ObClient *self,
+                                                           guint desktop)
+{
+    GSList *it;
+
+    for (it = self->transients; it; it = g_slist_next(it))
+        client_bring_non_application_windows_recursive(it->data, desktop);
+
+    if (client_normal(self) && !client_application(self) &&
+        self->desktop != desktop && self->desktop != DESKTOP_ALL)
+    {
+        client_set_desktop(self, desktop, FALSE, TRUE);
+    }
+}
+
+void client_bring_non_application_windows(ObClient *self)
+{
+    client_bring_non_application_windows_recursive(self, self->desktop);
+}
+
 void client_raise(ObClient *self)
 {
     action_run_string("Raise", self, CurrentTime);
This page took 0.029071 seconds and 4 git commands to generate.